optimization - 如何将 __m256i 向量除以整数变量?

标签 optimization x86 simd avx avx2

我想将 AVX2 向量除以一个常数。我访问过 this question和许多其他页面。看到可能有帮助的东西 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 .

关于optimization - 如何将 __m256i 向量除以整数变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42442325/

相关文章:

python - 一段 Julia 和 Python 代码的优化建议

java - 无法优化的 Java CPU 密集型计算示例

optimization - A53 的指令执行延迟

windows - MulDiv 是否比存储已知值和在其他代码中进行数学计算效率低

在实模式下用 Bresenham 的线算法计数,汇编

assembly - 在堆栈帧创建之前或之后插入寄存器之间有什么区别吗?

.net - 在通用 Windows 平台中将 Vector<T> 用于 SIMD

c - 在汇编中添加 float /双数

c# - 矢量化未提供预期的加速

android - 使用 NEON SIMD 进行短浮点转换和反之亦然