我有一个向量int16_t beta = {1,1,0,0,0,0,0,0}
。
我想用AVX2实现这个方程式
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)
实际上确实存在。但是还有其他方法可以实现整个公式,因此这个问题毕竟很有趣。
答案 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) * 1
或c[i] = 1 + 1 * 1
进行什么操作-我在这里假设正常的算术加法带有进位,与索引符号相反)。
因此,您可以删除索引:
c = a - (beta & b) + (!beta & b)
我不知道它是否可以很好地映射到AVX2内部函数,但我怀疑它确实可以。