From 0ce4dfb2069019f9390fbfbf50be3052443325d5 Mon Sep 17 00:00:00 2001 From: Alibek Zhakubayev Date: Thu, 2 Apr 2026 13:30:14 -0700 Subject: [PATCH] Fix AVX512_SPR build failure for 512-bit SIMD types (#5030) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- faiss/impl/fast_scan/LookupTableScaler.h | 10 ++++++---- faiss/impl/simdlib/simdlib_dispatch.h | 13 +++++++------ faiss/utils/simd_levels.h | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/faiss/impl/fast_scan/LookupTableScaler.h b/faiss/impl/fast_scan/LookupTableScaler.h index 1285cfcc1..fa22df53e 100644 --- a/faiss/impl/fast_scan/LookupTableScaler.h +++ b/faiss/impl/fast_scan/LookupTableScaler.h @@ -24,10 +24,11 @@ template struct DummyScaler { static constexpr int nscale = 0; static constexpr SIMDLevel SL256 = simd256_level_selector::value; + static constexpr SIMDLevel SL512 = simd512_level_selector::value; using simd32uint8 = simd32uint8_tpl; using simd16uint16 = simd16uint16_tpl; - using simd64uint8 = simd64uint8_tpl; - using simd32uint16 = simd32uint16_tpl; + using simd64uint8 = simd64uint8_tpl; + using simd32uint16 = simd32uint16_tpl; inline simd32uint8 lookup(const simd32uint8&, const simd32uint8&) const { FAISS_THROW_MSG("DummyScaler::lookup should not be called."); @@ -72,10 +73,11 @@ template struct NormTableScaler { static constexpr int nscale = 2; static constexpr SIMDLevel SL256 = simd256_level_selector::value; + static constexpr SIMDLevel SL512 = simd512_level_selector::value; using simd32uint8 = simd32uint8_tpl; using simd16uint16 = simd16uint16_tpl; - using simd64uint8 = simd64uint8_tpl; - using simd32uint16 = simd32uint16_tpl; + using simd64uint8 = simd64uint8_tpl; + using simd32uint16 = simd32uint16_tpl; int scale_int; simd16uint16 scale_simd; diff --git a/faiss/impl/simdlib/simdlib_dispatch.h b/faiss/impl/simdlib/simdlib_dispatch.h index d38bae3c3..5a8a0aaba 100644 --- a/faiss/impl/simdlib/simdlib_dispatch.h +++ b/faiss/impl/simdlib/simdlib_dispatch.h @@ -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 @@ -50,10 +51,10 @@ using simd32uint8 = simd32uint8_tpl; using simd8uint32 = simd8uint32_tpl; using simd8float32 = simd8float32_tpl; -// 512-bit -using simd512bit = simd512bit_tpl; -using simd32uint16 = simd32uint16_tpl; -using simd64uint8 = simd64uint8_tpl; -using simd16float32 = simd16float32_tpl; +// 512-bit (AVX512_SPR maps to AVX512 — same 512-bit integer ops) +using simd512bit = simd512bit_tpl; +using simd32uint16 = simd32uint16_tpl; +using simd64uint8 = simd64uint8_tpl; +using simd16float32 = simd16float32_tpl; } // namespace faiss diff --git a/faiss/utils/simd_levels.h b/faiss/utils/simd_levels.h index 52727bf0e..61d84b55f 100644 --- a/faiss/utils/simd_levels.h +++ b/faiss/utils/simd_levels.h @@ -86,6 +86,26 @@ struct simd256_level_selector { inline constexpr SIMDLevel SINGLE_SIMD_LEVEL_256 = simd256_level_selector::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 +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::value; + /// Number of float32 lanes for a given SIMD level. /// ARM_SVE is variable-width (128–2048 bits); no single constant is correct. template