c++ - 在 16 位添加 AVX2 时溢出而不是饱和

我想使用 AVX2 添加 2 个 unsigned 向量

__m256i i1 = _mm256_loadu_si256((__m256i *) si1);
__m256i i2 = _mm256_loadu_si256((__m256i *) si2);

__m256i result = _mm256_adds_epu16(i2, i1);

但是我需要溢出而不是饱和, _mm256_adds_epu16 确实与非矢量化代码相同,有什么解决方案吗?

回答1

使用正常的二进制包装 _mm256_add_epi16 而不是饱和 adds

二进制补码和 unsigned 加法/减法是相同的二进制运算,这也是现代计算机使用二进制补码的原因之一。正如 vpaddwhttps://www.felixcloutier.com/x86/paddb:paddw:paddd:paddq

_mm_cmpgt_epi32 之类的比较对符号敏感,但数学运算(和 cmpeq)不敏感。

Intel 选择的 intrinsics 名称可能看起来像是专门用于有符号整数的,但它们总是使用 episi 来表示同样适用于有符号和 unsigned 元素的事物。但是不,epu 意味着一个特定的 unsigned 事物,而 epi 可以是专门签名的操作,或者可以是在签名或 unsigned 上同等工作的事物。或者与签名无关的事情。

例如,_mm_and_si128 是纯按位的。 _mm_srli_epi32 是逻辑右移,在零中移位,就像 unsigned C 移位。不是符号位的副本,即 _mm_srai_epi32 (立即右移算术)。像 _mm_shuffle_epi32 这样的随机播放只是以块的形式移动数据。

_mm_mullo_epi16_mm_mullo_epi32 这样的非扩展乘法对于有符号或 unsigned 也是相同的。只有高半 _mm_mulhi_epu16 或加宽乘法 _mm_mul_epu32 有 unsigned 形式作为它们专门签名的 epi16/32 形式的对应物。

这也是为什么 386 只添加了一个标量整数 imul ecx, esi 形式,而不是一个 mul ecx, esi,因为只有 FLAGS 设置会有所不同,而不是整数结果。 SIMD 操作甚至没有 FLAGS 输出。

intrinsics 指南无益地将 _mm_mullo_epi16 描述为符号扩展并生成 32 位乘积,然后截断为低 32 位。 pmullwhttps://www.felixcloutier.com/x86/pmullw

有时英特尔的命名方案是有限的,比如 _mm_maddubs_epi16 是一个 u8 x i8 => 16 位加宽乘法,水平添加对(有符号饱和)。我通常必须查找 pmaddubsw 的内在函数,以提醒自己他们以输出元素宽度而不是输入来命名它。输入有不同的符号,所以如果他们必须选择一个,边,我想为输出命名是有意义的,有符号饱和可能发生在某些输入上,比如 pmaddwd

相似文章

r - `dplyr` 结果在过滤和分离行时发生变化

我有关于对话问题期间学生反应的数据。瞳孔数据在A*、B*和C*列中串在一起,以*intpl_new结尾的列显示插值的瞳孔区域values,以*dur结尾的列给出每个瞳孔的持续时间观察。数据框df包含两...

最新文章