如何将 __m256i 向量除以整数变量?
How to divide a __m256i vector by an integer variable?
我想将一个 AVX2 向量除以一个常数。我访问了this question and many other pages. Saw something that might help Fixed-point arithmetic,我没看懂。所以问题是这种划分是瓶颈。我尝试了两种方法:
首先,转换为float并用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);
第一种方法的问题是:不除法耗时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]);
}
嗯,好多了。但经过的时间仍然是 17ns。计算量太大,无法在此处显示。
问题是:有没有更快的方法优化这个内联函数?
您可以使用 _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);
}
请注意,这是假设 b > 1
。
我想将一个 AVX2 向量除以一个常数。我访问了this question and many other pages. Saw something that might help Fixed-point arithmetic,我没看懂。所以问题是这种划分是瓶颈。我尝试了两种方法:
首先,转换为float并用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);
第一种方法的问题是:不除法耗时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]);
}
嗯,好多了。但经过的时间仍然是 17ns。计算量太大,无法在此处显示。
问题是:有没有更快的方法优化这个内联函数?
您可以使用 _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);
}
请注意,这是假设 b > 1
。