我正在编写一些 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/