-
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 |
e513c0e
to
a8c9d82
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 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
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
a8c9d82
to
983f677
Compare
@mnorris11 has exported this pull request. If you are a Meta employee, you can view the originating Diff in 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
983f677
to
69dc49b
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 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
69dc49b
to
ed0296e
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 (v9) - - High level: there's 2 heaps at play during a `scan_codes` call. One is the uint16_t heap inside the HeapHandler, which tracks the best results for a given iteration of nprobe. The other tracks the results across iterations and is in float: heap_distances. At the end of each call, we add the best results from the current iteration (`curr_dists`) to the heap that persists over multiple `scan_codes` calls (`heap_distances`), then memcpy those to the output distances `distances`). __**Note**__: An alternative would be a `end()` type function which only memcpy to `distances` at the end. - Moved `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 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. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - 1. Specify the search params with a heap size (see create_ivfpqfs_params in the test for how to do it) 2. Pass it in when initializing scanner 3. 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. ~~Why do we need this io_simd_dis and io_simd_ids?~~ - Old, but keeping it struck out. This describes the uint16_t heap kept over multiple scans. ~~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.~~ Differential Revision: D80114737
ed0296e
to
30ff2ad
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 (v9) - - High level: there's 2 heaps at play during a `scan_codes` call. One is the uint16_t heap inside the HeapHandler, which tracks the best results for a given iteration of nprobe. The other tracks the results across iterations and is in float: heap_distances. At the end of each call, we add the best results from the current iteration (`curr_dists`) to the heap that persists over multiple `scan_codes` calls (`heap_distances`), then memcpy those to the output distances `distances`). __**Note**__: An alternative would be a `end()` type function which only memcpy to `distances` at the end. - Moved `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 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. https://github.com/facebookresearch/faiss/blob/514b44fca8542bafe8640adcbf1cccce1900f74c/faiss/IndexIVFFastScan.cpp#L918-L992 How to use - 1. Specify the search params with a heap size (see create_ivfpqfs_params in the test for how to do it) 2. Pass it in when initializing scanner 3. 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. ~~Why do we need this io_simd_dis and io_simd_ids?~~ - Old, but keeping it struck out. This describes the uint16_t heap kept over multiple scans. ~~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.~~ Differential Revision: D80114737
30ff2ad
to
e24954c
Compare
Description
Adds InvertedListScanner for IVFPQFastScan. Right now IVFPQFastScan does not support a Scanner because the codes are PQFS packed.
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
scan_codes
call. One is the uint16_t heap inside the HeapHandler, which tracks the best results for a given iteration of nprobe. The other tracks the results across iterations and is in float: heap_distances. At the end of each call, we add the best results from the current iteration (curr_dists
) to the heap that persists over multiplescan_codes
calls (heap_distances
), then memcpy those to the output distancesdistances
). Note: An alternative would be aend()
type function which only memcpy todistances
at the end.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, search_implem_10 processesn
queries at a time, just not batched. search_implem_10 has a simple loop overn
, 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.faiss/faiss/IndexIVFFastScan.cpp
Lines 918 to 992 in 514b44f
How to use
ntotal vs number of blocks?
Differential Revision: D80114737