-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Add InvertedListScanner for IVFPQFastScan #4537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This pull request was exported from Phabricator. Differential Revision: D80114737 |
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now it does not support it because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. It takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time. The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored it because it does not behave like other scanners, as it requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query, it does not matter. But if they want to use like the other Scanners, they can follow the example in test_lowlevel_ivf.cpp. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 Differential Revision: D80114737
e673fc2
to
f5dcfed
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
f5dcfed
to
efa9bca
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now it does not support it because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. It takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time. The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored it because it does not behave like other scanners, as it requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner, it does not matter because there's no need to use prior results. But if they want to use like the other Scanners, they can follow the example in test_lowlevel_ivf.cpp. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 Differential Revision: D80114737
efa9bca
to
6ffce9e
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
6ffce9e
to
2322351
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now it does not support it because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. It takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, it processes `n` queries at a time, just not batched. It is a simple loop over `n`, so it can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored it because it does not behave like other scanners, as it requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner (which I believe is Unicorn's use case), it does not matter because there's no need to use prior results and the user can follow the test named IVFPQFS_null_params. But if the user wants to use like the other Scanners, they can follow the other 2 tests in test_lowlevel_ivf.cpp that pass the heap size. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - If scanning multiple lists (mimicking nprobe > 1) 1. Specify the search params (see create_ivfpqfs_params) 2. Pass when initializing scanner 3. use as normal If scanning single list over the lifetime of this scanner 1. Pass nullptr for params when initializing scanner 2. Use as normal Differential Revision: D80114737
2322351
to
802173b
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
802173b
to
55c751c
Compare
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now it does not support it because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. It takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, it processes `n` queries at a time, just not batched. It is a simple loop over `n`, so it can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored it because it does not behave like other scanners, as it requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner (which I believe is Unicorn's use case), it does not matter because there's no need to use prior results and the user can follow the test named IVFPQFS_null_params. But if the user wants to use like the other Scanners, they can follow the other 2 tests in test_lowlevel_ivf.cpp that pass the heap size. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - If scanning multiple lists (mimicking nprobe > 1) 1. Specify the search params (see create_ivfpqfs_params) 2. Pass when initializing scanner 3. use as normal If scanning single list over the lifetime of this scanner 1. Pass nullptr for params when initializing scanner 2. Use as normal Differential Revision: D80114737
This pull request was exported from Phabricator. Differential Revision: D80114737 |
55c751c
to
b7d110f
Compare
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now IVFPQFastScan does not support a Scanner because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. IVFPQFastScanScanner takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, search_implem_10 processes `n` queries at a time, just not batched. search_implem_10 has a simple loop over `n`, so search_implem_10 can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored the test because IVFPQFastScanScanner does not behave like other scanners, as IVFPQFastScanScanner requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner (which I believe is Unicorn's use case), it does not matter because there's no need to use prior results and the user can follow the test named IVFPQFS_null_params. But if the user wants to use like the other Scanners, they can follow the other 2 tests in test_lowlevel_ivf.cpp that pass the heap size. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - If scanning multiple lists (mimicking nprobe > 1) 1. Specify the search params (see create_ivfpqfs_params) 2. Pass when initializing scanner 3. use as normal If scanning single list over the lifetime of this scanner 1. Pass nullptr for params when initializing scanner 2. Use as normal Differential Revision: D80114737
This pull request was exported from Phabricator. Differential Revision: D80114737 |
b7d110f
to
45a4e45
Compare
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now IVFPQFastScan does not support a Scanner because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. IVFPQFastScanScanner takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, search_implem_10 processes `n` queries at a time, just not batched. search_implem_10 has a simple loop over `n`, so search_implem_10 can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored the test because IVFPQFastScanScanner does not behave like other scanners, as IVFPQFastScanScanner requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner (which I believe is Unicorn's use case), it does not matter because there's no need to use prior results and the user can follow the test named IVFPQFS_null_params. But if the user wants to use like the other Scanners, they can follow the other 2 tests in test_lowlevel_ivf.cpp that pass the heap size. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - If scanning multiple lists (mimicking nprobe > 1) 1. Specify the search params (see create_ivfpqfs_params) 2. Pass when initializing scanner 3. use as normal If scanning single list over the lifetime of this scanner 1. Pass nullptr for params when initializing scanner 2. Use as normal Differential Revision: D80114737
This pull request was exported from Phabricator. Differential Revision: D80114737 |
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now IVFPQFastScan does not support a Scanner because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. IVFPQFastScanScanner takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, search_implem_10 processes `n` queries at a time, just not batched. search_implem_10 has a simple loop over `n`, so search_implem_10 can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored the test because IVFPQFastScanScanner does not behave like other scanners, as IVFPQFastScanScanner requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner (which I believe is Unicorn's use case), it does not matter because there's no need to use prior results and the user can follow the test named IVFPQFS_null_params. But if the user wants to use like the other Scanners, they can follow the other 2 tests in test_lowlevel_ivf.cpp that pass the heap size. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - If scanning multiple lists (mimicking nprobe > 1) 1. Specify the search params (see create_ivfpqfs_params) 2. Pass when initializing scanner 3. use as normal If scanning single list over the lifetime of this scanner 1. Pass nullptr for params when initializing scanner 2. Use as normal ntotal vs number of blocks? - - index.bbs is often 32 https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan)#implementation. This is the number of codes per block. Differential Revision: D80114737
45a4e45
to
e513c0e
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
Summary: Description - Adds InvertedListScanner for IVFPQFastScan. Right now IVFPQFastScan does not support a Scanner because the codes are PQFS packed. This is required from Unicorn to simplify the integration layer. We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new `IVFPQFastScanScanner.scan_codes`). Summary of changes - - Update HeapHandler in simd_result_handlers.h to return number of heap updates `nup`. Also add a bunch of junk aka `io_simd_dis` and `io_simd_ids` handling. More on that below. - Move `make_knn_handler` to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too. - Add the IVFPQFastScanScanner to IndexIVFPQFastScan. IVFPQFastScanScanner takes in SearchParams where the void* context is a struct containing max heap size when using this scanner (aka `k`). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, search_implem_10 processes `n` queries at a time, just not batched. search_implem_10 has a simple loop over `n`, so search_implem_10 can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10. - Changes to test_lowlevel_ivf.cpp to test this. Refactored the test because IVFPQFastScanScanner does not behave like other scanners, as IVFPQFastScanScanner requires `io_simd_dis` and `io_simd_ids` handling. Why do we need this io_simd_dis and io_simd_ids? - Other scanners can scan over multiple lists with `set_query` then `set_list`, then calling `scan_codes`. Why? Because they take the `float* distances`. The heap can operate on these floats to re-use values from last iteration. IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list. If the user is only setting 1 list and 1 query for the lifetime of this scanner (which I believe is Unicorn's use case), it does not matter because there's no need to use prior results and the user can follow the test named IVFPQFS_null_params. But if the user wants to use like the other Scanners, they can follow the other 2 tests in test_lowlevel_ivf.cpp that pass the heap size. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - If scanning multiple lists (mimicking nprobe > 1) 1. Specify the search params (see create_ivfpqfs_params) 2. Pass when initializing scanner 3. use as normal If scanning single list over the lifetime of this scanner 1. Pass nullptr for params when initializing scanner 2. Use as normal ntotal vs number of blocks? - - index.bbs is often 32 https://github.com/facebookresearch/faiss/wiki/Fast-accumulation-of-PQ-and-AQ-codes-(FastScan)#implementation. This is the number of codes per block. Differential Revision: D80114737
e513c0e
to
a8c9d82
Compare
This pull request was exported from Phabricator. Differential Revision: D80114737 |
Summary:
Description
Adds InvertedListScanner for IVFPQFastScan. Right now it does not support it because the codes are PQFS packed.
Summary of changes
nup
. Also add a bunch of junk akaio_simd_dis
andio_simd_ids
handling. More on that below.make_knn_handler
to the IndexIVFFastScan.h declaration so it can be used outside just IndexIVFFastScan.cpp. It is moved out of the anonymous namespace in the .cpp file too.k
). This impl for scan_codes is directly translated from search_implem_10 in in IndexIVFPQFastScan, because both search_implem_10 and scan_codes process 1 query and 1 invlist at a time (technically, it processesn
queries at a time, just not batched. It is a simple loop overn
, so it can be factored out to 1 query for this Scanner easily.). The only changes are removal of extraneous stuff from search_implem_10.io_simd_dis
andio_simd_ids
handling.Why do we need this io_simd_dis and io_simd_ids?
Other scanners can scan over multiple lists with
set_query
thenset_list
, then callingscan_codes
. Why? Because they take thefloat* distances
. The heap can operate on these floats to re-use values from last iteration.IVFPQFastScan is different. Codes are pq4 packed. The HeapHandler has to get initialized with values from scanning the prior list.
If the user is only setting 1 list and 1 query, it does not matter. But if they want to use like the other Scanners, they can follow the example in test_lowlevel_ivf.cpp.
We can implement a scanner based on the search_implem_10. We can't do distance_to_code but we can do the whole scan. (that is what is done in this diff in the new
IVFPQFastScanScanner.scan_codes
).faiss/faiss/IndexIVFFastScan.cpp
Lines 918 to 992 in 514b44f
Differential Revision: D80114737