mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-12 02:13:36 +00:00
Remove RaBitQStats debug counters from all RaBitQ handlers (#5102)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5102 ### THIS DIFF Remove the `RaBitQStats` struct, global variable, and all `#ifndef NDEBUG` stat-tracking blocks from the four RaBitQ index implementations: - `IndexRaBitQ` (non-FastScan flat) - `IndexIVFRaBitQ` (non-FastScan IVF) - `RaBitQHeapHandler` (FastScan flat, in IndexRaBitQFastScan.h) - `IVFRaBitQHeapHandler` (FastScan IVF, in IndexIVFRaBitQFastScan.h) The stats (`n_1bit_evaluations`, `n_multibit_evaluations`) were gated behind `#ifndef NDEBUG` and only available in dev builds. They tracked how many candidates passed the 1-bit lower-bound filter vs required full multibit refinement. While useful during initial development, they add per-vector overhead in dev builds (counter increments + two `omp atomic` updates per handle() call) and are no longer needed for ongoing work. All references are removed: the header, source file, SWIG bindings, xplat.bzl, and CMakeLists.txt registrations. ### CONTEXT Profiling of `IVFRaBitQHeapHandler::handle()` showed that debug stat tracking contributes measurable overhead in dev builds. Removing them simplifies the handler code and eliminates a source of noise in performance measurements. The filtering effectiveness can be measured externally via search result analysis when needed. Reviewed By: ALittleYam Differential Revision: D100931175 fbshipit-source-id: 7d148b63c5fca1b5f0e09040db2e3d77ffad7cbb
This commit is contained in:
committed by
meta-codesync[bot]
parent
796977a1ab
commit
74dceee903
@@ -120,7 +120,6 @@ set(FAISS_SRC
|
||||
impl/AdditiveQuantizer.cpp
|
||||
impl/RaBitQuantizer.cpp
|
||||
impl/RaBitQuantizerMultiBit.cpp
|
||||
impl/RaBitQStats.cpp
|
||||
impl/RaBitQUtils.cpp
|
||||
impl/ResidualQuantizer.cpp
|
||||
impl/LocalSearchQuantizer.cpp
|
||||
@@ -254,7 +253,6 @@ set(FAISS_HEADERS
|
||||
impl/Quantizer.h
|
||||
impl/RaBitQuantizer.h
|
||||
impl/RaBitQuantizerMultiBit.h
|
||||
impl/RaBitQStats.h
|
||||
impl/RaBitQUtils.h
|
||||
impl/ResidualQuantizer.h
|
||||
impl/ResultHandler.h
|
||||
|
||||
@@ -231,14 +231,6 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
||||
// Multi-bit: Two-stage search with adaptive filtering
|
||||
size_t nup = 0;
|
||||
|
||||
// Stats tracking for multi-bit two-stage search
|
||||
// n_1bit_evaluations: candidates evaluated using 1-bit lower bound
|
||||
// n_multibit_evaluations: candidates requiring full multi-bit distance
|
||||
#ifndef NDEBUG
|
||||
size_t local_1bit_evaluations = 0;
|
||||
size_t local_multibit_evaluations = 0;
|
||||
#endif
|
||||
|
||||
for (size_t j = 0; j < list_size; j++) {
|
||||
if (sel != nullptr) {
|
||||
int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
||||
@@ -248,18 +240,8 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
local_1bit_evaluations++;
|
||||
#endif
|
||||
|
||||
// Stage 1: Compute distance bound using 1-bit codes
|
||||
// For L2 (min-heap): use lower_bound to safely skip if it's
|
||||
// already worse than heap worst
|
||||
// For IP (max-heap): use upper_bound because with a lower bound,
|
||||
// we can't safely skip any candidate
|
||||
float est_distance = rabitq_dc->distance_to_code_1bit(codes);
|
||||
|
||||
// Extract f_error and g_error for filtering
|
||||
size_t code_size_base = (ivf_rabitq.d + 7) / 8;
|
||||
const rabitq_utils::SignBitFactorsWithError* base_fac =
|
||||
reinterpret_cast<
|
||||
@@ -273,10 +255,6 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
||||
handler.threshold,
|
||||
keep_max);
|
||||
if (should_refine) {
|
||||
#ifndef NDEBUG
|
||||
local_multibit_evaluations++;
|
||||
#endif
|
||||
// Lower bound is promising, compute full distance
|
||||
float dis = distance_to_code(codes);
|
||||
int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
||||
|
||||
@@ -287,14 +265,6 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
||||
codes += code_size;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Update global stats atomically
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_1bit_evaluations += local_1bit_evaluations;
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_multibit_evaluations += local_multibit_evaluations;
|
||||
#endif
|
||||
|
||||
return nup;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <faiss/Index.h>
|
||||
#include <faiss/IndexIVF.h>
|
||||
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
#include <faiss/impl/RaBitQuantizer.h>
|
||||
|
||||
namespace faiss {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <faiss/IndexIVFFastScan.h>
|
||||
#include <faiss/IndexIVFRaBitQ.h>
|
||||
#include <faiss/IndexRaBitQFastScan.h>
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
#include <faiss/impl/RaBitQUtils.h>
|
||||
#include <faiss/impl/RaBitQuantizer.h>
|
||||
#include <faiss/impl/fast_scan/rabitq_result_handler.h>
|
||||
@@ -271,11 +270,6 @@ void IVFRaBitQHeapHandler<C, SL>::handle(
|
||||
const size_t qb = context->qb > 0 ? context->qb : index->qb;
|
||||
const size_t d = index->d;
|
||||
|
||||
#ifndef NDEBUG
|
||||
size_t local_1bit_evaluations = 0;
|
||||
size_t local_multibit_evaluations = 0;
|
||||
#endif
|
||||
|
||||
for (size_t j = 0; j < max_positions; j++) {
|
||||
const int64_t result_id = this->adjust_id(b, j);
|
||||
if (result_id < 0) {
|
||||
@@ -291,9 +285,6 @@ void IVFRaBitQHeapHandler<C, SL>::handle(
|
||||
const uint8_t* base_ptr = aux_base + j * storage_size;
|
||||
|
||||
if (is_multibit) {
|
||||
#ifndef NDEBUG
|
||||
local_1bit_evaluations++;
|
||||
#endif
|
||||
const SignBitFactorsWithError& full_factors =
|
||||
*reinterpret_cast<const SignBitFactorsWithError*>(base_ptr);
|
||||
|
||||
@@ -312,9 +303,6 @@ void IVFRaBitQHeapHandler<C, SL>::handle(
|
||||
heap_dis[0],
|
||||
is_similarity);
|
||||
if (should_refine) {
|
||||
#ifndef NDEBUG
|
||||
local_multibit_evaluations++;
|
||||
#endif
|
||||
size_t local_offset = idx_base + j;
|
||||
float dist_full = compute_full_multibit_distance(
|
||||
local_q, q, local_offset, base_ptr);
|
||||
@@ -342,13 +330,6 @@ void IVFRaBitQHeapHandler<C, SL>::handle(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_1bit_evaluations += local_1bit_evaluations;
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_multibit_evaluations += local_multibit_evaluations;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class C, SIMDLevel SL>
|
||||
|
||||
+1
-34
@@ -106,17 +106,8 @@ struct Run_search_with_dc_res {
|
||||
resi.begin(q);
|
||||
dc_base->set_query(xq + d * q);
|
||||
|
||||
// Stats tracking for multi-bit two-stage search only
|
||||
// n_1bit_evaluations: candidates evaluated using 1-bit lower
|
||||
// bound n_multibit_evaluations: candidates requiring full
|
||||
// multi-bit distance
|
||||
#ifndef NDEBUG
|
||||
size_t local_1bit_evaluations = 0;
|
||||
size_t local_multibit_evaluations = 0;
|
||||
#endif
|
||||
|
||||
if (ex_bits == 0) {
|
||||
// 1-bit: Standard single-stage search (no stats tracking)
|
||||
// 1-bit: Standard single-stage search
|
||||
for (size_t i = 0; i < ntotal; i++) {
|
||||
if (res.is_in_selection(i)) {
|
||||
float dis = (*dc_base)(i);
|
||||
@@ -135,7 +126,6 @@ struct Run_search_with_dc_res {
|
||||
dc != nullptr,
|
||||
"Failed to cast to RaBitQDistanceComputer for two-stage search");
|
||||
|
||||
// Use appropriate comparison based on metric type
|
||||
bool is_similarity =
|
||||
is_similarity_metric(index->metric_type);
|
||||
|
||||
@@ -144,18 +134,9 @@ struct Run_search_with_dc_res {
|
||||
const uint8_t* code =
|
||||
index->codes.data() + i * index->code_size;
|
||||
|
||||
#ifndef NDEBUG
|
||||
local_1bit_evaluations++;
|
||||
#endif
|
||||
|
||||
// Stage 1: Compute distance bound using 1-bit codes
|
||||
// For L2 (min-heap): use lower_bound (est -
|
||||
// error) For IP (max-heap): use upper_bound (est
|
||||
// + error)
|
||||
float est_distance =
|
||||
dc->distance_to_code_1bit(code);
|
||||
|
||||
// Extract f_error for filtering
|
||||
size_t code_size_base = (index->d + 7) / 8;
|
||||
const rabitq_utils::SignBitFactorsWithError*
|
||||
base_fac = reinterpret_cast<
|
||||
@@ -163,7 +144,6 @@ struct Run_search_with_dc_res {
|
||||
SignBitFactorsWithError*>(
|
||||
code + code_size_base);
|
||||
|
||||
// Stage 2: Adaptive filtering
|
||||
bool should_refine =
|
||||
rabitq_utils::should_refine_candidate(
|
||||
est_distance,
|
||||
@@ -172,10 +152,6 @@ struct Run_search_with_dc_res {
|
||||
resi.threshold,
|
||||
is_similarity);
|
||||
if (should_refine) {
|
||||
#ifndef NDEBUG
|
||||
local_multibit_evaluations++;
|
||||
#endif
|
||||
// Compute full multi-bit distance
|
||||
float dist_full =
|
||||
dc->distance_to_code_full(code);
|
||||
resi.add_result(dist_full, i);
|
||||
@@ -184,15 +160,6 @@ struct Run_search_with_dc_res {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Update global stats atomically
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_1bit_evaluations += local_1bit_evaluations;
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_multibit_evaluations +=
|
||||
local_multibit_evaluations;
|
||||
#endif
|
||||
|
||||
resi.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <faiss/IndexFlatCodes.h>
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
#include <faiss/impl/RaBitQuantizer.h>
|
||||
|
||||
namespace faiss {
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include <faiss/IndexFastScan.h>
|
||||
#include <faiss/IndexRaBitQ.h>
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
#include <faiss/impl/RaBitQUtils.h>
|
||||
#include <faiss/impl/RaBitQuantizer.h>
|
||||
#include <faiss/impl/fast_scan/simd_result_handlers.h>
|
||||
@@ -213,21 +212,12 @@ struct RaBitQHeapHandler
|
||||
const uint8_t* aux_base = rabitq_index->codes.get() +
|
||||
block_idx * full_block_size + packed_block_size;
|
||||
|
||||
#ifndef NDEBUG
|
||||
size_t local_1bit_evaluations = 0;
|
||||
size_t local_multibit_evaluations = 0;
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < max_vectors; i++) {
|
||||
const size_t db_idx = base_db_idx + i;
|
||||
const float normalized_distance = d32tab[i] * one_a + bias;
|
||||
const uint8_t* base_ptr = aux_base + i * storage_size;
|
||||
|
||||
if (is_multi_bit) {
|
||||
#ifndef NDEBUG
|
||||
local_1bit_evaluations++;
|
||||
#endif
|
||||
|
||||
const SignBitFactorsWithError& full_factors =
|
||||
*reinterpret_cast<const SignBitFactorsWithError*>(
|
||||
base_ptr);
|
||||
@@ -252,9 +242,6 @@ struct RaBitQHeapHandler
|
||||
is_similarity);
|
||||
|
||||
if (should_refine) {
|
||||
#ifndef NDEBUG
|
||||
local_multibit_evaluations++;
|
||||
#endif
|
||||
float dist_full = compute_full_multibit_distance(db_idx, q);
|
||||
|
||||
if (Cfloat::cmp(heap_dis[0], dist_full)) {
|
||||
@@ -282,13 +269,6 @@ struct RaBitQHeapHandler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_1bit_evaluations += local_1bit_evaluations;
|
||||
#pragma omp atomic
|
||||
rabitq_stats.n_multibit_evaluations += local_multibit_evaluations;
|
||||
#endif
|
||||
}
|
||||
|
||||
void begin(const float* norms) override {
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
|
||||
namespace faiss {
|
||||
|
||||
// NOLINTNEXTLINE(facebook-avoid-non-const-global-variables)
|
||||
RaBitQStats rabitq_stats;
|
||||
|
||||
void RaBitQStats::reset() {
|
||||
n_1bit_evaluations = 0;
|
||||
n_multibit_evaluations = 0;
|
||||
}
|
||||
|
||||
double RaBitQStats::skip_percentage() const {
|
||||
const size_t copy_n_1bit_evaluations = n_1bit_evaluations;
|
||||
const size_t copy_n_multibit_evaluations = n_multibit_evaluations;
|
||||
return copy_n_1bit_evaluations > 0
|
||||
? 100.0 * (copy_n_1bit_evaluations - copy_n_multibit_evaluations) /
|
||||
copy_n_1bit_evaluations
|
||||
: 0.0;
|
||||
}
|
||||
|
||||
} // namespace faiss
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <faiss/impl/platform_macros.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace faiss {
|
||||
|
||||
/// Statistics for RaBitQ multi-bit two-stage search.
|
||||
///
|
||||
/// These stats are ONLY collected for multi-bit mode (nb_bits > 1).
|
||||
/// In 1-bit mode, there is no two-stage filtering - all candidates are
|
||||
/// evaluated with a single distance computation, so there is nothing
|
||||
/// meaningful to track. For 1-bit mode, both counters remain 0.
|
||||
///
|
||||
/// Multi-bit mode uses a two-stage search:
|
||||
/// Stage 1: Compute 1-bit lower bound distance for all candidates
|
||||
/// Stage 2: Compute full multi-bit distance only for promising candidates
|
||||
///
|
||||
/// The skip_percentage() metric measures filtering effectiveness:
|
||||
/// how many candidates were filtered out by the 1-bit lower bound
|
||||
/// without needing the more expensive multi-bit distance computation.
|
||||
///
|
||||
/// WARNING: Statistics are not robust to internal threading nor to
|
||||
/// concurrent RaBitQ searches. Use these values in a single-threaded
|
||||
/// context to accurately gauge RaBitQ's filtering effectiveness.
|
||||
/// Call reset() before search, then read stats after search completes.
|
||||
struct RaBitQStats {
|
||||
/// Number of candidates evaluated using 1-bit (lower bound) distance.
|
||||
/// This is the first stage of two-stage search in multi-bit mode.
|
||||
/// Always 0 in 1-bit mode (stats not tracked).
|
||||
size_t n_1bit_evaluations = 0;
|
||||
|
||||
/// Number of candidates that passed 1-bit filtering and required
|
||||
/// full multi-bit distance computation (second stage).
|
||||
/// Always 0 in 1-bit mode (stats not tracked).
|
||||
size_t n_multibit_evaluations = 0;
|
||||
|
||||
void reset();
|
||||
|
||||
/// Compute percentage of candidates skipped (filtered out by 1-bit stage).
|
||||
/// Returns 0 if no candidates were evaluated (including 1-bit mode).
|
||||
double skip_percentage() const;
|
||||
};
|
||||
|
||||
/// Global stats for RaBitQ indexes
|
||||
// NOLINTNEXTLINE(facebook-avoid-non-const-global-variables)
|
||||
FAISS_API extern RaBitQStats rabitq_stats;
|
||||
|
||||
} // namespace faiss
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include <faiss/impl/FaissAssert.h>
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
#include <faiss/impl/RaBitQUtils.h>
|
||||
#include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
|
||||
#include <faiss/impl/fast_scan/simd_result_handlers.h>
|
||||
|
||||
@@ -203,7 +203,6 @@ typedef uint64_t size_t;
|
||||
#include <faiss/IndexNeuralNetCodec.h>
|
||||
|
||||
#include <faiss/impl/RaBitQuantizer.h>
|
||||
#include <faiss/impl/RaBitQStats.h>
|
||||
#include <faiss/impl/RaBitQUtils.h>
|
||||
#include <faiss/IndexRaBitQ.h>
|
||||
#include <faiss/IndexRaBitQFastScan.h>
|
||||
@@ -668,7 +667,6 @@ void gpu_sync_all_devices()
|
||||
%include <faiss/IndexNeuralNetCodec.h>
|
||||
|
||||
%include <faiss/impl/RaBitQuantizer.h>
|
||||
%include <faiss/impl/RaBitQStats.h>
|
||||
%include <faiss/impl/RaBitQUtils.h>
|
||||
%include <faiss/IndexRaBitQ.h>
|
||||
%include <faiss/IndexRaBitQFastScan.h>
|
||||
|
||||
Reference in New Issue
Block a user