c - 使用SIMD右移32位压缩负数

标签 c sse avx mmx

我正在编写一些 SSE/AVX 代码,并且有一个任务将打包的有符号 32 位整数除以 2 的补码。当值为正时,这种移位工作正常,但由于移位符号位,它会产生负值的错误结果。
是否有任何 SIMD 操作可以让我进行移位并保留符号位的位置?谢谢

最佳答案

对于 16 位和 32 位元素大小,SSE2/AVX2 可以选择算术1 与逻辑右移。 (对于 64 位元素,在 AVX512 之前仅逻辑可用)。

使用 _mm_srai_epi32 ( psrad ) 而不是 _mm_srli_epi32 ( psrld )。

参见Intel's intrinsics guide ,以及 SSE 标签 wiki https://stackoverflow.com/tags/sse/info 中的其他链接。 (如果你愿意的话,可以过滤它以排除 AVX512,因为现在它非常困惑,所有 3 种尺寸的所有屏蔽版本......)

或者只需查看 asm 指令集引用,其中包括具有它们的指令的内在函数。在 http://felixcloutier.com/x86/index.html 中搜索“算术”找到您想要的类次。

请注意,a=算术与l=逻辑,而不是通常的无符号内联命名方案epu32。 asm 助记符简单且一致(例如 Packed Shift Right Arithmetic Dword = psrad)。


算术右移也可用于 AVX2 变量移位(vpsravd),以及立即移位的一变量所有元素版本。


脚注1:

算术右移移入符号位的副本,而不是零

这正确地实现了 2 的补码除以 2 的幂,并向负无穷大舍入,这与从 C 符号除法中得到的向零截断不同。查看 int foo(int a){return a/4;} 的 asm 输出,了解编译器如何根据移位实现有符号除法语义。

关于c - 使用SIMD右移32位压缩负数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51853561/

相关文章:

c - e^-x 麦克劳林系列扩展

c - scanf在c中的数学表达式

x86 - 将数据放入 SIMD 寄存器需要多少个周期?

performance - 用于二进制相关的SSE向量的Popcount吗?

intrinsics - 在 AVX 内在函数中使用 xmm 参数

c++ - 打包和解交错两个 __m256 寄存器

c - 为什么c中出现 '%' conversions than data arguments错误时输出随机整数?

c - 无法使用 papi.h 运行 PAPI 代码,错误 : cannot open shared object file in GCC

c++ - 上证所该向上舍入时向下舍入

c - 使用 gcc 优化 -mavx 失败?