如何用整数变量划分__m256i向量?

Mar*_*tin 4 optimization x86 simd avx avx2

我想将AVX2向量除以常数.我访问了这个问题和许多其他页面.看到可能有助于定点运算的东西,我不明白.所以问题在于这种划分是瓶颈.我试过两种方法:

首先,使用AVX指令进行浮动并执行操作:

//outside the bottleneck:
__m256i veci16; // containing some integer numbers (16x16-bit numbers)
__m256 div_v = _mm256_set1_ps(div);

//inside the bottlneck
//some calculations which make veci16
vecps = _mm256_castsi256_ps (veci16);
vecps = _mm256_div_ps (vecps, div_v);
veci16 = _mm256_castps_si256 (vecps);
_mm256_storeu_si256((__m256i *)&output[i][j], veci16);
Run Code Online (Sandbox Code Playgroud)

使用第一种方法,问题是:没有分割经过的时间是5ns,并且经过的时间是大约60ns.

其次,我存储到一个数组并加载它像这样:

int t[16] ;
inline __m256i _mm256_div_epi16 (__m256i a , int b){

    _mm256_store_si256((__m256i *)&t[0] , a);
    t[0]/=b; t[1]/=b; t[2]/=b; t[3]/=b; t[4]/=b; t[5]/=b; t[6]/=b; t[7]/=b;
    t[8]/=b; t[9]/=b; t[10]/=b; t[11]/=b; t[12]/=b; t[13]/=b; t[14]/=b; t[15]/=b;
    return _mm256_load_si256((__m256i *)&t[0]);         
}
Run Code Online (Sandbox Code Playgroud)

嗯,这样更好.但仍然流逝的时间是17ns.这里的计算太多了.

问题是:有没有更快的方法来优化这个内联函数?

Pau*_*l R 7

你可以这样做_mm256_mulhrs_epi16.这会进行定点乘法运算,因此您只需将被乘数向量设置为32768 / b:

inline __m256i _mm256_div_epi16 (const __m256i va, const int b)
{
    __m256i vb = _mm256_set1_epi16(32768 / b);
    return _mm256_mulhrs_epi16(va, vb);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这是假设b > 1.