Fix AVX512_SPR build failure for 512-bit SIMD types (#5030)

Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5030

The `faiss_avx512_spr` CMake target fails to compile because 512-bit SIMD
type aliases (`simd32uint16`, `simd64uint8`, etc.) resolve to empty primary
templates when `SINGLE_SIMD_LEVEL = AVX512_SPR`. Only `AVX512` and `NONE`
have explicit template specializations.

This adds `simd512_level_selector` (analogous to existing
`simd256_level_selector`) that maps `AVX512_SPR -> AVX512` for 512-bit
types. This is correct because AVX512_SPR uses the same 512-bit integer
SIMD instructions as AVX512 — SPR-specific gains come from separate
instruction sets (BF16, FP16, VNNI) used in different code paths.

Changes:
- `simd_levels.h`: Add `simd512_level_selector` and `SINGLE_SIMD_LEVEL_512`
- `simdlib_dispatch.h`: Route 512-bit aliases through `SINGLE_SIMD_LEVEL_512`;
  also check `COMPILE_SIMD_AVX512_SPR` in include guard
- `LookupTableScaler.h`: Use `simd512_level_selector` for 512-bit types in
  `DummyScaler` and `NormTableScaler`

Reviewed By: mnorris11

Differential Revision: D99306837

fbshipit-source-id: 49e71415c155b9328dc76ff0cd492f718060ff1e
This commit is contained in:
Alibek Zhakubayev
2026-04-02 13:30:14 -07:00
committed by meta-codesync[bot]
parent aef066ac0e
commit 0ce4dfb206
3 changed files with 33 additions and 10 deletions
+6 -4
View File
@@ -24,10 +24,11 @@ template <SIMDLevel SL = SINGLE_SIMD_LEVEL>
struct DummyScaler {
static constexpr int nscale = 0;
static constexpr SIMDLevel SL256 = simd256_level_selector<SL>::value;
static constexpr SIMDLevel SL512 = simd512_level_selector<SL>::value;
using simd32uint8 = simd32uint8_tpl<SL256>;
using simd16uint16 = simd16uint16_tpl<SL256>;
using simd64uint8 = simd64uint8_tpl<SL>;
using simd32uint16 = simd32uint16_tpl<SL>;
using simd64uint8 = simd64uint8_tpl<SL512>;
using simd32uint16 = simd32uint16_tpl<SL512>;
inline simd32uint8 lookup(const simd32uint8&, const simd32uint8&) const {
FAISS_THROW_MSG("DummyScaler::lookup should not be called.");
@@ -72,10 +73,11 @@ template <SIMDLevel SL = SINGLE_SIMD_LEVEL>
struct NormTableScaler {
static constexpr int nscale = 2;
static constexpr SIMDLevel SL256 = simd256_level_selector<SL>::value;
static constexpr SIMDLevel SL512 = simd512_level_selector<SL>::value;
using simd32uint8 = simd32uint8_tpl<SL256>;
using simd16uint16 = simd16uint16_tpl<SL256>;
using simd64uint8 = simd64uint8_tpl<SL>;
using simd32uint16 = simd32uint16_tpl<SL>;
using simd64uint8 = simd64uint8_tpl<SL512>;
using simd32uint16 = simd32uint16_tpl<SL512>;
int scale_int;
simd16uint16 scale_simd;
+7 -6
View File
@@ -22,7 +22,8 @@
// Only per-SIMD TUs (compiled with -mavx2 etc.) see the platform
// specializations. In static mode: only the compiled-in level is available.
#if defined(COMPILE_SIMD_AVX512) && defined(__AVX512F__)
#if (defined(COMPILE_SIMD_AVX512) || defined(COMPILE_SIMD_AVX512_SPR)) && \
defined(__AVX512F__)
// AVX512 includes AVX2 (simdlib_avx512.h includes simdlib_avx2.h)
#include <faiss/impl/simdlib/simdlib_avx512.h>
@@ -50,10 +51,10 @@ using simd32uint8 = simd32uint8_tpl<SINGLE_SIMD_LEVEL_256>;
using simd8uint32 = simd8uint32_tpl<SINGLE_SIMD_LEVEL_256>;
using simd8float32 = simd8float32_tpl<SINGLE_SIMD_LEVEL_256>;
// 512-bit
using simd512bit = simd512bit_tpl<SINGLE_SIMD_LEVEL>;
using simd32uint16 = simd32uint16_tpl<SINGLE_SIMD_LEVEL>;
using simd64uint8 = simd64uint8_tpl<SINGLE_SIMD_LEVEL>;
using simd16float32 = simd16float32_tpl<SINGLE_SIMD_LEVEL>;
// 512-bit (AVX512_SPR maps to AVX512 — same 512-bit integer ops)
using simd512bit = simd512bit_tpl<SINGLE_SIMD_LEVEL_512>;
using simd32uint16 = simd32uint16_tpl<SINGLE_SIMD_LEVEL_512>;
using simd64uint8 = simd64uint8_tpl<SINGLE_SIMD_LEVEL_512>;
using simd16float32 = simd16float32_tpl<SINGLE_SIMD_LEVEL_512>;
} // namespace faiss
+20
View File
@@ -86,6 +86,26 @@ struct simd256_level_selector {
inline constexpr SIMDLevel SINGLE_SIMD_LEVEL_256 =
simd256_level_selector<SINGLE_SIMD_LEVEL>::value;
/***************************************************************
* Helper to select the appropriate 512-bit SIMD level.
*
* For 512-bit SIMD types (simd32uint16, simd64uint8, etc.), maps:
* AVX512_SPR → AVX512 (512-bit ops share the same instructions)
* AVX512 → AVX512
* NONE → NONE
***************************************************************/
template <SIMDLevel SL>
struct simd512_level_selector {
static constexpr SIMDLevel value =
(SL == SIMDLevel::AVX512_SPR) ? SIMDLevel::AVX512 : SL;
};
/// SINGLE_SIMD_LEVEL mapped to 512-bit: use this for 512-bit simd types
/// (simd32uint16, simd64uint8, etc.) which don't have AVX512_SPR
/// specializations (AVX512_SPR uses the same 512-bit integer ops as AVX512).
inline constexpr SIMDLevel SINGLE_SIMD_LEVEL_512 =
simd512_level_selector<SINGLE_SIMD_LEVEL>::value;
/// Number of float32 lanes for a given SIMD level.
/// ARM_SVE is variable-width (128–2048 bits); no single constant is correct.
template <SIMDLevel SL>