mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-11 22:50:00 +00:00
DD: give PQCodeDistanceScalar a SIMD level so the AVX2 path cannot run AVX512 code (#5719)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5719 `PQCodeDistanceScalar<PQDecoderT>` is defined in a header and instantiated in every per-SIMD translation unit (`avx2.cpp` with `-mavx2`, `avx512.cpp` with `-mavx512*`, the generic TU). All copies have the same symbol, so the linker keeps one. In a dynamic-dispatch x86 build it kept the `-mavx512*` copy: `PQCodeDistanceScalar<PQDecoderGeneric>::distance_four_codes` contained 93 `zmm` instructions and was called from `PQCodeDistance<PQDecoderGeneric, SIMDLevel::AVX2>`. On a CPU without AVX512 (AMD Milan, T1_MLN), IVFPQ search with a non-8-bit PQ (`PQDecoderGeneric`, also `PQDecoder16`) on the AVX2 path raises SIGILL. Found by running the faiss C++ tests under the vendored `qemu-x86_64`, which has no AVX512: `IVFPQFastScan.*` (`test_fast_scan_distance_to_code`) died with SIGILL at `vmovdqa64 ...,%zmm0` in that function. Same class as S672695 (AVX512 code reached on a CPU without it); found before any non-AVX512 host was added to the Cogwheel suite. Fix: template `PQCodeDistanceScalar` on `SIMDLevel` as well, as the DD migration guide prescribes for code compiled per level, so each TU's instantiation is a distinct symbol. `PQCodeDistance<D, SL>` passes its level; the NONE and ARM_NEON specializations in `pq_code_distance-generic.h` pass theirs. Applied to both definitions (`impl/pq_code_distance/pq_code_distance-inl.h` and `utils/pq_code_distance.h`). `SL` defaults to `SIMDLevel::NONE` so code outside faiss that names only the decoder keeps compiling: `unicorn/features/encoders/PQFSTable.h` uses `faiss::PQCodeDistanceScalar<PQDecoderT>`, and without the default 15 Unicorn targets failed to build on this diff. Reviewed By: mnorris11 Differential Revision: D124399620 fbshipit-source-id: ece1baf0e1eba39712f881976dea33fe22b265c1
This commit is contained in:
committed by
meta-codesync[bot]
parent
07979b10e6
commit
5d635f354c
@@ -20,8 +20,8 @@ inline float pq_code_distance_8bit_single_impl<SIMDLevel::NONE>(
|
|||||||
size_t M,
|
size_t M,
|
||||||
const float* sim_table,
|
const float* sim_table,
|
||||||
const uint8_t* code) {
|
const uint8_t* code) {
|
||||||
return PQCodeDistanceScalar<PQDecoder8>::distance_single_code(
|
return PQCodeDistanceScalar<PQDecoder8, SIMDLevel::NONE>::
|
||||||
M, 8, sim_table, code);
|
distance_single_code(M, 8, sim_table, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
||||||
@@ -37,7 +37,7 @@ inline void pq_code_distance_8bit_four_impl<SIMDLevel::NONE>(
|
|||||||
float& result1,
|
float& result1,
|
||||||
float& result2,
|
float& result2,
|
||||||
float& result3) {
|
float& result3) {
|
||||||
PQCodeDistanceScalar<PQDecoder8>::distance_four_codes(
|
PQCodeDistanceScalar<PQDecoder8, SIMDLevel::NONE>::distance_four_codes(
|
||||||
M,
|
M,
|
||||||
8,
|
8,
|
||||||
sim_table,
|
sim_table,
|
||||||
@@ -60,8 +60,8 @@ inline float pq_code_distance_8bit_single_impl<SIMDLevel::ARM_NEON>(
|
|||||||
size_t M,
|
size_t M,
|
||||||
const float* sim_table,
|
const float* sim_table,
|
||||||
const uint8_t* code) {
|
const uint8_t* code) {
|
||||||
return PQCodeDistanceScalar<PQDecoder8>::distance_single_code(
|
return PQCodeDistanceScalar<PQDecoder8, SIMDLevel::ARM_NEON>::
|
||||||
M, 8, sim_table, code);
|
distance_single_code(M, 8, sim_table, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
||||||
@@ -77,7 +77,7 @@ inline void pq_code_distance_8bit_four_impl<SIMDLevel::ARM_NEON>(
|
|||||||
float& result1,
|
float& result1,
|
||||||
float& result2,
|
float& result2,
|
||||||
float& result3) {
|
float& result3) {
|
||||||
PQCodeDistanceScalar<PQDecoder8>::distance_four_codes(
|
PQCodeDistanceScalar<PQDecoder8, SIMDLevel::ARM_NEON>::distance_four_codes(
|
||||||
M,
|
M,
|
||||||
8,
|
8,
|
||||||
sim_table,
|
sim_table,
|
||||||
|
|||||||
@@ -62,10 +62,14 @@ namespace pq_code_distance {
|
|||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
/// Scalar PQ code distance implementation.
|
/// Scalar PQ code distance implementation.
|
||||||
/// Templated only on decoder type, independent of SIMD level.
|
|
||||||
/// Used directly by non-PQDecoder8 decoders (PQDecoder16,
|
/// Used directly by non-PQDecoder8 decoders (PQDecoder16,
|
||||||
/// PQDecoderGeneric) and as fallback for PQDecoder8 at NONE/NEON.
|
/// PQDecoderGeneric) and as fallback for PQDecoder8 at NONE/NEON.
|
||||||
template <typename PQDecoderT>
|
// SL keeps each SIMD-level TU's instantiation a distinct symbol. Without it
|
||||||
|
// the linker merges them and may keep one compiled with -mavx512*, which
|
||||||
|
// then runs on the AVX2 path and raises SIGILL on CPUs without AVX512.
|
||||||
|
// The default keeps callers outside faiss that name only the decoder (e.g.
|
||||||
|
// unicorn/features/encoders/PQFSTable.h) compiling; faiss passes SL itself.
|
||||||
|
template <typename PQDecoderT, SIMDLevel SL = SIMDLevel::NONE>
|
||||||
struct PQCodeDistanceScalar {
|
struct PQCodeDistanceScalar {
|
||||||
using PQDecoder = PQDecoderT;
|
using PQDecoder = PQDecoderT;
|
||||||
|
|
||||||
@@ -168,7 +172,7 @@ struct PQCodeDistance {
|
|||||||
if constexpr (std::is_same_v<PQDecoderT, PQDecoder8>) {
|
if constexpr (std::is_same_v<PQDecoderT, PQDecoder8>) {
|
||||||
return pq_code_distance_8bit_single_impl<SL>(M, sim_table, code);
|
return pq_code_distance_8bit_single_impl<SL>(M, sim_table, code);
|
||||||
} else {
|
} else {
|
||||||
return PQCodeDistanceScalar<PQDecoderT>::distance_single_code(
|
return PQCodeDistanceScalar<PQDecoderT, SL>::distance_single_code(
|
||||||
M, nbits, sim_table, code);
|
M, nbits, sim_table, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +202,7 @@ struct PQCodeDistance {
|
|||||||
result2,
|
result2,
|
||||||
result3);
|
result3);
|
||||||
} else {
|
} else {
|
||||||
PQCodeDistanceScalar<PQDecoderT>::distance_four_codes(
|
PQCodeDistanceScalar<PQDecoderT, SL>::distance_four_codes(
|
||||||
M,
|
M,
|
||||||
nbits,
|
nbits,
|
||||||
sim_table,
|
sim_table,
|
||||||
|
|||||||
@@ -53,10 +53,14 @@ namespace pq_code_distance {
|
|||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
/// Scalar PQ code distance implementation.
|
/// Scalar PQ code distance implementation.
|
||||||
/// Templated only on decoder type, independent of SIMD level.
|
|
||||||
/// Used directly by non-PQDecoder8 decoders (PQDecoder16,
|
/// Used directly by non-PQDecoder8 decoders (PQDecoder16,
|
||||||
/// PQDecoderGeneric) and as fallback for PQDecoder8 at NONE/NEON.
|
/// PQDecoderGeneric) and as fallback for PQDecoder8 at NONE/NEON.
|
||||||
template <typename PQDecoderT>
|
// SL keeps each SIMD-level TU's instantiation a distinct symbol. Without it
|
||||||
|
// the linker merges them and may keep one compiled with -mavx512*, which
|
||||||
|
// then runs on the AVX2 path and raises SIGILL on CPUs without AVX512.
|
||||||
|
// The default keeps callers outside faiss that name only the decoder (e.g.
|
||||||
|
// unicorn/features/encoders/PQFSTable.h) compiling; faiss passes SL itself.
|
||||||
|
template <typename PQDecoderT, SIMDLevel SL = SIMDLevel::NONE>
|
||||||
struct PQCodeDistanceScalar {
|
struct PQCodeDistanceScalar {
|
||||||
using PQDecoder = PQDecoderT;
|
using PQDecoder = PQDecoderT;
|
||||||
|
|
||||||
@@ -160,7 +164,7 @@ struct PQCodeDistance {
|
|||||||
if constexpr (std::is_same_v<PQDecoderT, PQDecoder8>) {
|
if constexpr (std::is_same_v<PQDecoderT, PQDecoder8>) {
|
||||||
return pq_code_distance_single_impl<SL>(M, nbits, sim_table, code);
|
return pq_code_distance_single_impl<SL>(M, nbits, sim_table, code);
|
||||||
} else {
|
} else {
|
||||||
return PQCodeDistanceScalar<PQDecoderT>::distance_single_code(
|
return PQCodeDistanceScalar<PQDecoderT, SL>::distance_single_code(
|
||||||
M, nbits, sim_table, code);
|
M, nbits, sim_table, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,7 +195,7 @@ struct PQCodeDistance {
|
|||||||
result2,
|
result2,
|
||||||
result3);
|
result3);
|
||||||
} else {
|
} else {
|
||||||
PQCodeDistanceScalar<PQDecoderT>::distance_four_codes(
|
PQCodeDistanceScalar<PQDecoderT, SL>::distance_four_codes(
|
||||||
M,
|
M,
|
||||||
nbits,
|
nbits,
|
||||||
sim_table,
|
sim_table,
|
||||||
|
|||||||
Reference in New Issue
Block a user