mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-12 02:13:36 +00:00
Replace dispatch_HammingComputer with with_HammingComputer (#5126)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5126 Replace the dispatch_HammingComputer + Run_XXX consumer struct pattern with with_HammingComputer that takes a C++20 template lambda directly. This eliminates boilerplate wrapper structs across 8 files. Before: struct Run_foo { using T = void; template<class HC, class... T> void f(T... a) { foo<HC>(a...); } }; Run_foo r; dispatch_HammingComputer(code_size, r, args...); After: with_HammingComputer(code_size, [&]<class HC>() { foo<HC>(args...); }); Reviewed By: algoriddle Differential Revision: D101350351 fbshipit-source-id: 02a346e8c33ffdb49153cbe13415b748f0a1e847
This commit is contained in:
committed by
meta-codesync[bot]
parent
ed7e1f2435
commit
e23c66175d
@@ -309,14 +309,6 @@ struct FlatHammingDis : DistanceComputer {
|
||||
}
|
||||
};
|
||||
|
||||
struct BuildDistanceComputer {
|
||||
using T = DistanceComputer*;
|
||||
template <class HammingComputer>
|
||||
DistanceComputer* f(IndexBinaryFlat* flat_storage) {
|
||||
return new FlatHammingDis<HammingComputer>(*flat_storage);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
DistanceComputer* IndexBinaryHNSW::get_distance_computer() const {
|
||||
@@ -324,8 +316,10 @@ DistanceComputer* IndexBinaryHNSW::get_distance_computer() const {
|
||||
FAISS_THROW_IF_NOT_MSG(
|
||||
flat_storage != nullptr,
|
||||
"IndexBinaryHNSW requires IndexBinaryFlat storage");
|
||||
BuildDistanceComputer bd;
|
||||
return dispatch_HammingComputer(code_size, bd, flat_storage);
|
||||
return with_HammingComputer(
|
||||
code_size, [&]<class HammingComputer>() -> DistanceComputer* {
|
||||
return new FlatHammingDis<HammingComputer>(*flat_storage);
|
||||
});
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
|
||||
@@ -175,14 +175,6 @@ void search_single_query_template(
|
||||
} while (fe.next());
|
||||
}
|
||||
|
||||
struct Run_search_single_query {
|
||||
using T = void;
|
||||
template <class HammingComputer, class... Types>
|
||||
T f(Types*... args) {
|
||||
search_single_query_template<HammingComputer>(*args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class SearchResults>
|
||||
void search_single_query(
|
||||
const IndexBinaryHash& index,
|
||||
@@ -191,9 +183,10 @@ void search_single_query(
|
||||
size_t& n0,
|
||||
size_t& nlist,
|
||||
size_t& ndis) {
|
||||
Run_search_single_query r;
|
||||
dispatch_HammingComputer(
|
||||
index.code_size, r, &index, &q, &res, &n0, &nlist, &ndis);
|
||||
with_HammingComputer(index.code_size, [&]<class HammingComputer>() {
|
||||
search_single_query_template<HammingComputer>(
|
||||
index, q, res, n0, nlist, ndis);
|
||||
});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@@ -343,14 +336,6 @@ static void verify_shortlist(
|
||||
}
|
||||
}
|
||||
|
||||
struct Run_verify_shortlist {
|
||||
using T = void;
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(Types... args) {
|
||||
verify_shortlist<HammingComputer>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class SearchResults>
|
||||
void search_1_query_multihash(
|
||||
const IndexBinaryMultiHash& index,
|
||||
@@ -387,9 +372,9 @@ void search_1_query_multihash(
|
||||
ndis += shortlist.size();
|
||||
|
||||
// verify shortlist
|
||||
Run_verify_shortlist r;
|
||||
dispatch_HammingComputer(
|
||||
index.code_size, r, index.storage, xi, shortlist, res);
|
||||
with_HammingComputer(index.code_size, [&]<class HammingComputer>() {
|
||||
verify_shortlist<HammingComputer>(index.storage, xi, shortlist, res);
|
||||
});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
+18
-42
@@ -784,40 +784,16 @@ void search_knn_hamming_per_invlist(
|
||||
}
|
||||
}
|
||||
|
||||
struct Run_search_knn_hamming_per_invlist {
|
||||
using T = void;
|
||||
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(Types... args) {
|
||||
search_knn_hamming_per_invlist<HammingComputer>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool store_pairs>
|
||||
struct Run_search_knn_hamming_count {
|
||||
using T = void;
|
||||
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(Types... args) {
|
||||
search_knn_hamming_count<HammingComputer, store_pairs>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
struct BuildScanner {
|
||||
using T = BinaryInvertedListScanner*;
|
||||
|
||||
template <class HammingComputer>
|
||||
T f(size_t code_size, bool store_pairs) {
|
||||
return new IVFBinaryScannerL2<HammingComputer>(code_size, store_pairs);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BinaryInvertedListScanner* IndexBinaryIVF::get_InvertedListScanner(
|
||||
bool store_pairs) const {
|
||||
BuildScanner bs;
|
||||
return dispatch_HammingComputer(code_size, bs, code_size, store_pairs);
|
||||
return with_HammingComputer(
|
||||
code_size,
|
||||
[&]<class HammingComputer>() -> BinaryInvertedListScanner* {
|
||||
return new IVFBinaryScannerL2<HammingComputer>(
|
||||
code_size, store_pairs);
|
||||
});
|
||||
}
|
||||
|
||||
void IndexBinaryIVF::search_preassigned(
|
||||
@@ -831,23 +807,23 @@ void IndexBinaryIVF::search_preassigned(
|
||||
bool store_pairs,
|
||||
const IVFSearchParameters* params) const {
|
||||
if (per_invlist_search) {
|
||||
Run_search_knn_hamming_per_invlist r;
|
||||
// clang-format off
|
||||
dispatch_HammingComputer(
|
||||
code_size, r, this, n, x, k,
|
||||
cidx, cdis, dis, idx, store_pairs, params);
|
||||
// clang-format on
|
||||
with_HammingComputer(code_size, [&]<class HammingComputer>() {
|
||||
search_knn_hamming_per_invlist<HammingComputer>(
|
||||
this, n, x, k, cidx, cdis, dis, idx, store_pairs, params);
|
||||
});
|
||||
} else if (use_heap) {
|
||||
search_knn_hamming_heap(
|
||||
this, n, x, k, cidx, cdis, dis, idx, store_pairs, params);
|
||||
} else if (store_pairs) { // !use_heap && store_pairs
|
||||
Run_search_knn_hamming_count<true> r;
|
||||
dispatch_HammingComputer(
|
||||
code_size, r, this, n, x, cidx, k, dis, idx, params);
|
||||
with_HammingComputer(code_size, [&]<class HammingComputer>() {
|
||||
search_knn_hamming_count<HammingComputer, true>(
|
||||
this, n, x, cidx, k, dis, idx, params);
|
||||
});
|
||||
} else { // !use_heap && !store_pairs
|
||||
Run_search_knn_hamming_count<false> r;
|
||||
dispatch_HammingComputer(
|
||||
code_size, r, this, n, x, cidx, k, dis, idx, params);
|
||||
with_HammingComputer(code_size, [&]<class HammingComputer>() {
|
||||
search_knn_hamming_count<HammingComputer, false>(
|
||||
this, n, x, cidx, k, dis, idx, params);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-12
@@ -1167,23 +1167,15 @@ struct IVFPQScannerT : QueryTables {
|
||||
}
|
||||
}
|
||||
|
||||
template <class SearchResultType>
|
||||
struct Run_scan_list_polysemous_hc {
|
||||
using T = void;
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(const IVFPQScannerT* scanner, Types... args) {
|
||||
scanner->scan_list_polysemous_hc<HammingComputer, SearchResultType>(
|
||||
args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class SearchResultType>
|
||||
void scan_list_polysemous(
|
||||
size_t ncode,
|
||||
const uint8_t* codes,
|
||||
SearchResultType& res) const {
|
||||
Run_scan_list_polysemous_hc<SearchResultType> r;
|
||||
dispatch_HammingComputer(pq.code_size, r, this, ncode, codes, res);
|
||||
with_HammingComputer(pq.code_size, [&]<class HammingComputer>() {
|
||||
this->scan_list_polysemous_hc<HammingComputer, SearchResultType>(
|
||||
ncode, codes, res);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -299,15 +299,6 @@ struct IVFScanner : InvertedListScanner {
|
||||
}
|
||||
};
|
||||
|
||||
struct BuildScanner {
|
||||
using T = InvertedListScanner*;
|
||||
|
||||
template <class HammingComputer>
|
||||
static T f(const IndexIVFSpectralHash* index, bool store_pairs) {
|
||||
return new IVFScanner<HammingComputer>(index, store_pairs);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
InvertedListScanner* IndexIVFSpectralHash::get_InvertedListScanner(
|
||||
@@ -315,8 +306,10 @@ InvertedListScanner* IndexIVFSpectralHash::get_InvertedListScanner(
|
||||
const IDSelector* sel,
|
||||
const IVFSearchParameters*) const {
|
||||
FAISS_THROW_IF_NOT(!sel);
|
||||
BuildScanner bs;
|
||||
return dispatch_HammingComputer(code_size, bs, this, store_pairs);
|
||||
return with_HammingComputer(
|
||||
code_size, [&]<class HammingComputer>() -> InvertedListScanner* {
|
||||
return new IVFScanner<HammingComputer>(this, store_pairs);
|
||||
});
|
||||
}
|
||||
|
||||
void IndexIVFSpectralHash::replace_vt(VectorTransform* vt_in, bool own) {
|
||||
|
||||
+11
-19
@@ -323,14 +323,6 @@ size_t polysemous_inner_loop(
|
||||
return n_pass_i;
|
||||
}
|
||||
|
||||
struct Run_polysemous_inner_loop {
|
||||
using T = size_t;
|
||||
template <class HammingComputer, class... Types>
|
||||
size_t f(Types... args) {
|
||||
return polysemous_inner_loop<HammingComputer>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void IndexPQ::search_core_polysemous(
|
||||
@@ -381,17 +373,17 @@ void IndexPQ::search_core_polysemous(
|
||||
maxheap_heapify(k, heap_dis, heap_ids);
|
||||
|
||||
if (!generalized_hamming) {
|
||||
Run_polysemous_inner_loop r;
|
||||
n_pass += dispatch_HammingComputer(
|
||||
pq.code_size,
|
||||
r,
|
||||
this,
|
||||
dis_table_qi,
|
||||
q_code,
|
||||
k,
|
||||
heap_dis,
|
||||
heap_ids,
|
||||
param_polysemous_ht);
|
||||
n_pass += with_HammingComputer(
|
||||
pq.code_size, [&]<class HammingComputer>() -> size_t {
|
||||
return polysemous_inner_loop<HammingComputer>(
|
||||
this,
|
||||
dis_table_qi,
|
||||
q_code,
|
||||
k,
|
||||
heap_dis,
|
||||
heap_ids,
|
||||
param_polysemous_ht);
|
||||
});
|
||||
|
||||
} else { // generalized hamming
|
||||
switch (pq.code_size) {
|
||||
|
||||
+12
-43
@@ -332,30 +332,6 @@ void hamming_range_search(
|
||||
}
|
||||
}
|
||||
|
||||
struct Run_hammings_knn_hc {
|
||||
using T = void;
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(Types... args) {
|
||||
hammings_knn_hc<HammingComputer>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
struct Run_hammings_knn_mc {
|
||||
using T = void;
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(Types... args) {
|
||||
hammings_knn_mc<HammingComputer>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
struct Run_hamming_range_search {
|
||||
using T = void;
|
||||
template <class HammingComputer, class... Types>
|
||||
void f(Types... args) {
|
||||
hamming_range_search<HammingComputer>(args...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/* Functions to maps vectors to bits. Assume proper allocation done beforehand,
|
||||
@@ -511,19 +487,10 @@ void hammings_knn_hc(
|
||||
int order,
|
||||
ApproxTopK_mode_t approx_topk_mode,
|
||||
const faiss::IDSelector* sel) {
|
||||
Run_hammings_knn_hc r;
|
||||
dispatch_HammingComputer(
|
||||
ncodes,
|
||||
r,
|
||||
ncodes,
|
||||
ha,
|
||||
a,
|
||||
b,
|
||||
nb,
|
||||
order,
|
||||
true,
|
||||
approx_topk_mode,
|
||||
sel);
|
||||
with_HammingComputer(ncodes, [&]<class HammingComputer>() {
|
||||
hammings_knn_hc<HammingComputer>(
|
||||
ncodes, ha, a, b, nb, order, true, approx_topk_mode, sel);
|
||||
});
|
||||
}
|
||||
|
||||
void hammings_knn_mc(
|
||||
@@ -536,9 +503,10 @@ void hammings_knn_mc(
|
||||
int32_t* __restrict distances,
|
||||
int64_t* __restrict labels,
|
||||
const faiss::IDSelector* sel) {
|
||||
Run_hammings_knn_mc r;
|
||||
dispatch_HammingComputer(
|
||||
ncodes, r, ncodes, a, b, na, nb, k, distances, labels, sel);
|
||||
with_HammingComputer(ncodes, [&]<class HammingComputer>() {
|
||||
hammings_knn_mc<HammingComputer>(
|
||||
ncodes, a, b, na, nb, k, distances, labels, sel);
|
||||
});
|
||||
}
|
||||
|
||||
void hamming_range_search(
|
||||
@@ -550,9 +518,10 @@ void hamming_range_search(
|
||||
size_t code_size,
|
||||
RangeSearchResult* result,
|
||||
const faiss::IDSelector* sel) {
|
||||
Run_hamming_range_search r;
|
||||
dispatch_HammingComputer(
|
||||
code_size, r, a, b, na, nb, radius, code_size, result, sel);
|
||||
with_HammingComputer(code_size, [&]<class HammingComputer>() {
|
||||
hamming_range_search<HammingComputer>(
|
||||
a, b, na, nb, radius, code_size, result, sel);
|
||||
});
|
||||
}
|
||||
|
||||
/* Count number of matches given a max threshold */
|
||||
|
||||
@@ -56,30 +56,29 @@ SPECIALIZED_HC(64);
|
||||
#undef SPECIALIZED_HC
|
||||
|
||||
/***************************************************************************
|
||||
* Dispatching function that takes a code size and a consumer object
|
||||
* the consumer object should contain a retun type t and a operation template
|
||||
* function f() that must be called to perform the operation.
|
||||
* Dispatching function that takes a code size and a C++20 template lambda.
|
||||
* The lambda is called with the appropriate HammingComputer type:
|
||||
* with_HammingComputer(code_size, [&]<class HammingComputer>() { ... });
|
||||
**************************************************************************/
|
||||
|
||||
template <class Consumer, class... Types>
|
||||
typename Consumer::T dispatch_HammingComputer(
|
||||
int code_size,
|
||||
Consumer& consumer,
|
||||
Types... args) {
|
||||
template <class F>
|
||||
decltype(auto) with_HammingComputer(int code_size, F&& f) {
|
||||
switch (code_size) {
|
||||
#define DISPATCH_HC(CODE_SIZE) \
|
||||
case CODE_SIZE: \
|
||||
return consumer.template f<HammingComputer##CODE_SIZE>(args...);
|
||||
DISPATCH_HC(4);
|
||||
DISPATCH_HC(8);
|
||||
DISPATCH_HC(16);
|
||||
DISPATCH_HC(20);
|
||||
DISPATCH_HC(32);
|
||||
DISPATCH_HC(64);
|
||||
case 4:
|
||||
return f.template operator()<HammingComputer4>();
|
||||
case 8:
|
||||
return f.template operator()<HammingComputer8>();
|
||||
case 16:
|
||||
return f.template operator()<HammingComputer16>();
|
||||
case 20:
|
||||
return f.template operator()<HammingComputer20>();
|
||||
case 32:
|
||||
return f.template operator()<HammingComputer32>();
|
||||
case 64:
|
||||
return f.template operator()<HammingComputer64>();
|
||||
default:
|
||||
return consumer.template f<HammingComputerDefault>(args...);
|
||||
return f.template operator()<HammingComputerDefault>();
|
||||
}
|
||||
#undef DISPATCH_HC
|
||||
}
|
||||
|
||||
} // namespace faiss
|
||||
|
||||
Reference in New Issue
Block a user