如何基于另一个0或1个元素的向量有条件地否定AVX2 int16_t向量?

时间:2018-08-17 08:40:10

标签: c++ optimization simd avx avx2

我有一个向量int16_t beta = {1,1,0,0,0,0,0,0}

我想用AVX2实现这个方程式

enter image description here

c[i] = a[i] + (-1)^beta[i] * b[i]

其中a,b,c和beta均为int16_t的AVX2向量。


我已经弄清楚了,如果我可以将1映射到-32768,就可以避免乘法运算。我的意思是,可以使用simd内部函数的OR和NEGATE函数来翻转向量b的符号。

我确实知道可以使用左移操作将1映射到-32768,但是avx2没有任何移位操作 1 。有什么办法可以通过simd有效地将1映射到-32768?


编辑者的脚注1:_mm256_slli_epi16(x, 15)实际上确实存在。但是还有其他方法可以实现整个公式,因此这个问题毕竟很有趣。

2 个答案:

答案 0 :(得分:4)

有一种使用_mm256_sign_epi16进行条件否定的快速方法。掩码的格式不正确,但是可以通过向每个元素添加0x7FFF将其转换为正确的格式,因此:

__m256i masks = _mm256_add_epi16(beta, _mm256_set1_epi16(0x7FFF));
__m256i res = _mm256_add_epi16(a, _mm256_sign_epi16(b, masks));

答案 1 :(得分:0)

您可以变换

c[i] = a[i] + (-1)^beta[i] * b[i]

c[i] = a[i] - (beta[i] AND b[i]) + ((NOT beta[i]) AND b[i])

因为原始公式的意思是“如果设置了beta [i],请减去此位,否则将其添加”。
(我不知道您打算为c[i] = 0 + (-1) * 1c[i] = 1 + 1 * 1进行什么操作-我在这里假设正常的算术加法带有进位,与索引符号相反)。
因此,您可以删除索引:

c = a - (beta & b) + (!beta & b)

我不知道它是否可以很好地映射到AVX2内部函数,但我怀疑它确实可以。