使用SIMD,如何将8位掩码扩展为16位掩码?

我正在尝试使用simd重写这段代码:

int16_t v;
int32_t a[16];
int8_t b[32];
...
((int16_t *)a[i])[0] = b[i]==1? -v:v;
((int16_t *)a[i])[1] = b[i]==1? -v:v;

我正在考虑使用_mm256_cmpeq_epi8来生成掩码矢量,之后我可以使用_mm256_and_si256和_mm256_andnot_si256来执行值选择.
问题是b [i]是8位整数而v是16位.
如果掩码向量类似于{0xff,0x00,0xff,0x00 …},则需要将其扩展为{0xffff,0x0000,0xffff,0x0000 …}以执行16位值选择.
我怎样才能做到这一点?
(对不起我的英语不好)

编辑:
我从this question的灵感中找到了解决方案.
_mm256_shuffle_epi256只能在128位通道内执行.
所以我将_mm256i掩码分成2个_mm128i寄存器.然后用_mm256_broadcastsi128_si256和_mm256_shuffle_epi256我得到了结果.

最佳答案 有一个解决方案:

int16_t v;
int32_t a[16];
int8_t b[32];

//((int16_t *)a[i])[0] = b[i]==1? -v:v;
//((int16_t *)a[i])[1] = b[i]==1? -v:v;

__m256i _1 = _mm256_set1_epi8(1);
__m256i _b = _mm256_loadu_si256((__m256i*)b);

__m256i mask8i = _mm256_cmpeq_epi8(_b, _1); // 8-bit compare mask

__m256i permutedMask8i = _mm256_permute4x64_epi64(mask8i, 0xD8);
__m256i mask16iLo = _mm256_unpacklo_epi8(permutedMask8i, permutedMask8i); // low part of 16-bit compare mask
__m256i mask16iHi = _mm256_unpackhi_epi8(permutedMask8i, permutedMask8i); // high part of 16-bit compare mask

__m256i positiveV = _mm256_set1_epi16(-v); //positive mask condition
__m256i negativeV = _mm256_set1_epi16(v);  //negative mask condition

__m256i _aLo = _mm256_blendv_epi8(negativeV, positiveV, mask16iLo);
__m256i _aHi = _mm256_blendv_epi8(negativeV, positiveV, mask16iHi);

_mm256_storeu_si256((__m256i*)a + 0, _aLo);
_mm256_storeu_si256((__m256i*)a + 1, _aHi);
点赞