From 83071917e903581542670a87a036f5d02e13fb82 Mon Sep 17 00:00:00 2001 From: mstembera Date: Sun, 27 Jul 2025 16:09:01 -0700 Subject: [PATCH] Optimize find_nnz() using VBMI2 about a 0.7% speedup for the x86-64-avx512icl ARCH closes https://github.com/official-stockfish/Stockfish/pull/6186 No functional change --- .../layers/affine_transform_sparse_input.h | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/nnue/layers/affine_transform_sparse_input.h b/src/nnue/layers/affine_transform_sparse_input.h index e77c98f8c..069210304 100644 --- a/src/nnue/layers/affine_transform_sparse_input.h +++ b/src/nnue/layers/affine_transform_sparse_input.h @@ -82,7 +82,36 @@ void find_nnz(const std::int32_t* RESTRICT input, std::uint16_t* RESTRICT out, IndexType& count_out) { - #ifdef USE_AVX512 + #if defined(USE_AVX512ICL) + + constexpr IndexType SimdWidthIn = 16; // 512 bits / 32 bits + constexpr IndexType SimdWidthOut = 32; // 512 bits / 16 bits + constexpr IndexType NumChunks = InputDimensions / SimdWidthOut; + const __m512i increment = _mm512_set1_epi16(SimdWidthOut); + __m512i base = _mm512_set_epi16(31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + + IndexType count = 0; + for (IndexType i = 0; i < NumChunks; ++i) + { + const __m512i inputV0 = _mm512_load_si512(input + i * 2 * SimdWidthIn); + const __m512i inputV1 = _mm512_load_si512(input + i * 2 * SimdWidthIn + SimdWidthIn); + + // Get a bitmask and gather non zero indices + const __mmask32 nnzMask = _mm512_kunpackw(_mm512_test_epi32_mask(inputV1, inputV1), + _mm512_test_epi32_mask(inputV0, inputV0)); + + // Avoid _mm512_mask_compressstoreu_epi16() as it's 256 uOps on Zen4 + __m512i nnz = _mm512_maskz_compress_epi16(nnzMask, base); + _mm512_storeu_epi16(out + count, nnz); + + count += popcount(nnzMask); + base = _mm512_add_epi16(base, increment); + } + count_out = count; + + #elif defined(USE_AVX512) + constexpr IndexType SimdWidth = 16; // 512 bits / 32 bits constexpr IndexType NumChunks = InputDimensions / SimdWidth; const __m512i increment = _mm512_set1_epi32(SimdWidth);