溢出而不是饱和在16位添加AVX2



我想使用AVX2添加2个无符号向量

__m256i i1 = _mm256_loadu_si256((__m256i *) si1);
__m256i i2 = _mm256_loadu_si256((__m256i *) si2);
__m256i result = _mm256_adds_epu16(i2, i1);

然而,我需要溢出而不是饱和,_mm256_adds_epu16与非向量化代码相同,是否有任何解决方案?

使用正常二进制换行_mm256_add_epi16代替饱和式adds

2的补码和无符号加减法是相同的二进制操作,这就是现代计算机使用2的补码的原因之一。正如vpaddw的asm手动条目所提到的,这些指令可以用于有符号或无符号整数。(intrinsic指南条目根本没有提到签名,因此对澄清这种混淆没有多大帮助。)

_mm_cmpgt_epi32这样的比较是对签名敏感的,但是数学运算(和cmpeq)不敏感。


Intel选择的intrinsic名称可能看起来像是专门针对有符号整数的,但他们总是使用episi来处理在有符号和无符号元素上同样工作的东西。但是不,epu意味着一个特定的无符号的东西,而epi可以是特定的有符号的操作,也可以是在有符号和无符号上同样工作的东西。或者签名无关的东西。

例如,_mm_and_si128是纯位的。_mm_srli_epi32是一个逻辑右移位,在零中移位,类似于无符号C移位。不是复制符号位,那是_mm_srai_epi32(右移直接算术)。像_mm_shuffle_epi32这样的shuffle只是在块中移动数据。

_mm_mullo_epi16_mm_mullo_epi32这样的非加宽乘法对于有符号和无符号也是一样的。只有高半部分_mm_mulhi_epu16或扩大倍数_mm_mul_epu32具有无符号形式,作为其特定符号epi16/32形式的对应。

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

intrinsic指南将_mm_mullo_epi16描述为符号扩展并产生32位产品,然后截断到低32位。pmullw的asm手册也将其描述为以这种方式签名,它似乎将其作为带签名的pmulhw的伴侣来谈论。(并且有一些错误,如描述AVX1VPMULLW xmm1, xmm2, xmm3/m128形式乘以32位dword元素,可能是pmulld的复制/粘贴错误)

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

最新更新