mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-11 22:50:00 +00:00
Hoist per-list allocations out of the IVF fast-scan search loops (#5717)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5717 `IndexIVFFastScan::search_implem_12` and `search_implem_14` allocate a fresh `AlignedTable<uint8_t> LUT`, `q_map` and `lut_entries` for every inverted list they visit, and call `get_block_stride()`, which heap-allocates a `CodePacker` on each call; `search_implem_10` makes the same `get_block_stride()` call per list. These loops run on OpenMP worker threads, so with jemalloc heap profiling on (the production default for task 0 of every job) on aarch64 every sampled allocation pays libunwind's slow fallback at the `__kmp_invoke_microtask` frame. gdb thread snapshots of the D124204736 build under profiling (`hr_ivf1024_rabitqfs4`, Grace): of 206 threads caught in jemalloc's `prof_backtrace`, 163 were in `posix_memalign` called from `search_implem_12` (the per-list LUT), 6 in its per-list vectors and 4 in `get_block_stride()`. This allocates those buffers once per call / per thread, sized for the largest batch (`qbs2` queries x `dim12`), and computes the block stride once. Each iteration still uses only the first `nc` entries, so the search is unchanged. Reviewed By: junjieqi Differential Revision: D124387842 fbshipit-source-id: 6bcfe66270fcc0b208b0c88aaf578fea952f6174
This commit is contained in:
committed by
meta-codesync[bot]
parent
39079668a8
commit
db6aa06d96
@@ -1063,6 +1063,7 @@ void IndexIVFFastScan::search_implem_10(
|
||||
// Allocate probe_map once and reuse it
|
||||
std::vector<int> probe_map;
|
||||
probe_map.reserve(1);
|
||||
const size_t block_stride = get_block_stride();
|
||||
|
||||
for (idx_t i = 0; i < n; i++) {
|
||||
const uint8_t* LUT = nullptr;
|
||||
@@ -1137,7 +1138,7 @@ void IndexIVFFastScan::search_implem_10(
|
||||
codes.get(),
|
||||
LUT,
|
||||
context.pq2x4_scale,
|
||||
get_block_stride());
|
||||
block_stride);
|
||||
|
||||
ndis += ls;
|
||||
nlist_visited++;
|
||||
@@ -1229,6 +1230,9 @@ void IndexIVFFastScan::search_implem_12(
|
||||
// Allocate vectors once and reuse them
|
||||
std::vector<int> probe_map;
|
||||
probe_map.reserve(actual_qbs2);
|
||||
std::vector<int> q_map(actual_qbs2), lut_entries(actual_qbs2);
|
||||
AlignedTable<uint8_t> LUT(actual_qbs2 * dim12);
|
||||
const size_t block_stride = get_block_stride();
|
||||
|
||||
size_t i0 = 0;
|
||||
uint64_t t_copy_pack = 0, t_scan = 0;
|
||||
@@ -1255,8 +1259,6 @@ void IndexIVFFastScan::search_implem_12(
|
||||
// re-organize LUTs and biases into the right order
|
||||
int nc = static_cast<int>(i1 - i0);
|
||||
|
||||
std::vector<int> q_map(nc), lut_entries(nc);
|
||||
AlignedTable<uint8_t> LUT(nc * dim12);
|
||||
memset(LUT.get(), -1, nc * dim12);
|
||||
int qbs_for_list = pq4_preferred_qbs(nc);
|
||||
|
||||
@@ -1306,7 +1308,7 @@ void IndexIVFFastScan::search_implem_12(
|
||||
codes.get(),
|
||||
LUT.get(),
|
||||
context.pq2x4_scale,
|
||||
get_block_stride());
|
||||
block_stride);
|
||||
// prepare for next loop
|
||||
i0 = i1;
|
||||
}
|
||||
@@ -1464,6 +1466,9 @@ void IndexIVFFastScan::search_implem_14(
|
||||
// Allocate probe_map once per thread and reuse it
|
||||
std::vector<int> probe_map;
|
||||
probe_map.reserve(actual_qbs2);
|
||||
std::vector<int> q_map(actual_qbs2), lut_entries(actual_qbs2);
|
||||
AlignedTable<uint8_t> LUT(actual_qbs2 * dim12);
|
||||
const size_t block_stride = get_block_stride();
|
||||
|
||||
#pragma omp for schedule(dynamic)
|
||||
for (idx_t cluster = 0; cluster < static_cast<idx_t>(ses.size());
|
||||
@@ -1477,8 +1482,6 @@ void IndexIVFFastScan::search_implem_14(
|
||||
// re-organize LUTs and biases into the right order
|
||||
int nc = static_cast<int>(i1 - i0);
|
||||
|
||||
std::vector<int> q_map(nc), lut_entries(nc);
|
||||
AlignedTable<uint8_t> LUT(nc * dim12);
|
||||
memset(LUT.get(), -1, nc * dim12);
|
||||
int qbs_for_list = pq4_preferred_qbs(nc);
|
||||
|
||||
@@ -1529,7 +1532,7 @@ void IndexIVFFastScan::search_implem_14(
|
||||
codes.get(),
|
||||
LUT.get(),
|
||||
context.pq2x4_scale,
|
||||
get_block_stride());
|
||||
block_stride);
|
||||
}
|
||||
|
||||
// labels is in-place for HeapHC
|
||||
|
||||
Reference in New Issue
Block a user