【发布时间】:2020-02-04 04:49:53
【问题描述】:
我正在寻找一种用掩码(例如__mmask16)划分压缩 16 位整数的解决方案。 _mm512_mask_div_epi32 内在函数似乎不错;但是它们只支持压缩的 32 位整数,这不必要地迫使我在使用前将压缩的 16 位扩展为压缩的 32 位。
【问题讨论】:
标签: c intrinsics avx avx512
我正在寻找一种用掩码(例如__mmask16)划分压缩 16 位整数的解决方案。 _mm512_mask_div_epi32 内在函数似乎不错;但是它们只支持压缩的 32 位整数,这不必要地迫使我在使用前将压缩的 16 位扩展为压缩的 32 位。
【问题讨论】:
标签: c intrinsics avx avx512
_mm512_mask_div_epi32 不是真正的内在函数;这是一个英特尔 SVML 功能。 x86 没有 SIMD 整数除法,只有 SIMD FP double 和 float。
如果您的除数向量是编译时常量(或重复用于多个除数),请参阅 https://libdivide.com/ 了解使用乘法逆的精确除法。
否则,最好的办法是转换为可以精确表示每个 16 位整数的单精度 FP。如果_mm512_mask_div_epi32 做了任何额外的工作来处理 FP32 不能 完全代表所有可能的int32_t 的事实,那么这对您的用例来说是浪费的。
(一些未来的 CPU 可能在 IA 内核中支持某种 16 位 FP,而不仅仅是 GPU,但目前利用高吞吐量硬件 div/sqrt SIMD 执行单元的最佳方式是通过转换为float。例如,对于带有单个微指令的 Skylake vdivps ymm,每 5 个时钟周期一个 __m256,或者对于带有 3 个微指令的 __m512,每 10 个时钟周期一个 vdivps zmm)
【讨论】:
_mm512_mask_div_epi32 没有任何对应的asm,或者不是你所说的真正的内在。我猜它会被编译成普通的整数除法 asm,因此不能减少运行时间。我将尝试转换为一些vdivps 函数,然后转换回epi32。
_mm512_mask_div_epi32 的内部实现使用 SIMD float 甚至 double 来避免 32 位整数的舍入错误,如果它被记录为始终准确的话.不解包为整数除法的标量!它还可以将舍入模式设置为截断,以确保在进行截断转换回整数之前,结果不会在幅度上四舍五入。 (AVX512 可以通过舍入模式覆盖有效地做到这一点。)