我想要改组__m256i向量的元素。 并且有一个内在的_mm256_shuffle_epi8可以做类似的事情,但它并没有执行交叉通道随机播放。
如何使用AVX2指令进行操作?
答案 0 :(得分:8)
有一种方法可以模拟这个操作,但它不是很漂亮:
const __m256i K0 = _mm256_setr_epi8(
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0);
const __m256i K1 = _mm256_setr_epi8(
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70);
inline const __m256i Shuffle(const __m256i & value, const __m256i & shuffle)
{
return _mm256_or_si256(_mm256_shuffle_epi8(value, _mm256_add_epi8(shuffle, K0)),
_mm256_shuffle_epi8(_mm256_permute4x64_epi64(value, 0x4E), _mm256_add_epi8(shuffle, K1)));
}
答案 1 :(得分:1)
首先 - 澄清 - 英特尔的通常规范要求在每个字节的每个字节中的位0-3中定义混洗模式。由于您试图进行跨车道随机播放,因此您的随机播放模式也会使用位4来表示YMM寄存器中位于15以上位置索引的字节。
假设:您想要随机播放的内容是YMM0,模式是YMM1。
代码如下:
mask_pattern_0 db 0FH
mask_pattern_1 db 10H
vpbroadcastb ymm2,byte ptr mask_pattern_0 ; Load the mask
vmovdqu ymm5,ymm2
vpsubb ymm3,ymm2,ymm1 ; YMM3 has neg for all those exceeding 15 in original shuffle pattern
vpsignb ymm4,ymm1,ymm3 ; YMM4 replicates shuffle pattern with a neg at all those that are above 15 in the original shuffle pattern
vperm2i128 ymm2,ymm0,ymm0,00010001b ; Save the upper 128 bits of the target YMM0 to YMM2 in both upper and lower 128 bits
vperm2i128 ymm0,ymm0,ymm0,00100000b ; This replicates the lower 128 bits of YMM0 to upper 128 bits of YMM0
vpshufb ymm0,ymm0,ymm4 ; This places all those with index below 16 to appropriate place, and sets a zero to other bytes
;We now process the entries in shuffle pattern with index above 15
vpsubb ymm3,ymm1,ymm5 ; Now all those above 15 have a positive value
vpsignb ymm4,ymm1,ymm3 ; YMM4 has negatives for all those below 15 in original shuffle pattern YMM1
vpbroadcastb ymm5,byte ptr mask_pattern_1 ; Load the mask value 10H
vpsubb ymm4,ymm4,ymm5
vpshufb ymm2,ymm2,ymm4 ; Save the shuffle in YMM2
vpaddb ymm0,ymm0,ymm2
这也确保了YMM1中包含的模式不受影响 - 与VPSHUFB指令一样。
相信这会有所帮助......