You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求17x17位截断平方运算的高效AVX2实现方案

AVX2 Implementation of 17x17 Truncated Squarer (Top 15 Bits)

Core Approach

For a 17-bit unsigned integer x, its square x² is a 34-bit value. We need the top 15 bits of this result, which is equivalent to x² >> 19 (since 34 - 15 = 19).

AVX2 provides efficient fixed-shift instructions and unsigned 32-bit multiplication intrinsics that let us compute this directly without relying on variable shifts (which are not supported for 16-bit elements and inefficient for 32-bit).

Implementation Code

#include <immintrin.h>

// Input: __m256i x_vec - 8x32-bit elements, each containing a 17-bit unsigned integer (low 17 bits valid)
// Output: __m256i result_vec - 8x32-bit elements, each containing the top 15 bits of x² (low 15 bits valid)
__m256i avx2_truncated_square_17to15(__m256i x_vec) {
    // Compute high 32 bits of x*x (each element is (x*x) >> 32)
    __m256i x_sq_high = _mm256_mul_epu32(x_vec, x_vec);
    // Compute low 32 bits of x*x (each element is (x*x) & 0xFFFFFFFF)
    __m256i x_sq_low = _mm256_mullo_epi32(x_vec, x_vec);
    
    // Shift high bits to align with the top 15 bits of x²: (x*x >>32) <<13 = x*x >>19 (high portion)
    __m256i high_shifted = _mm256_slli_epi32(x_sq_high, 13);
    // Shift low bits to get the remaining portion of x² >>19
    __m256i low_shifted = _mm256_srli_epi32(x_sq_low, 19);
    
    // Combine the two portions
    __m256i result = _mm256_add_epi32(high_shifted, low_shifted);
    // Mask to keep only the top 15 bits (0x7FFF = 15 bits all 1)
    return _mm256_and_si256(result, _mm256_set1_epi32(0x7FFF));
}

// Optional: Pack result to 16-bit elements if needed
__m256i avx2_truncated_square_17to15_packed(__m256i x_vec) {
    __m256i result_32 = avx2_truncated_square_17to15(x_vec);
    // Pack 32-bit elements to 16-bit (unsigned saturation, safe since max value is 0x7FFF)
    return _mm256_packus_epi32(result_32, result_32);
}

Correctness Verification

  • For x = 2^17 - 1 (max 17-bit value), x² = (2^17 -1)^2 = 2^34 - 2^18 +1 = 17179607041. x² >>19 = 32767 (0x7FFF), which matches the masked result.
  • For x = 1024 (2^10), x² = 1048576, x² >>19 = 2, which the code correctly computes.
  • Edge case x=0 returns 0 as expected.

Performance Notes

  • Uses only fixed-shift instructions (_mm256_slli_epi32, _mm256_srli_epi32) which are single-cycle on most x86 CPUs.
  • Avoids variable-shift intrinsics entirely, eliminating the performance overhead you encountered with _mm256_srlv_epi32.
  • The core computation uses just 6 intrinsics (excluding constant setup), far more efficient than compiler-autovectorized code you mentioned (25 instructions).

内容的提问来源于stack exchange,提问作者njuffa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:25:54