我在理解 AVX 洗牌内在函数如何为 8 位工作时遇到了一些问题
I've some problems understanding how AVX shuffle intrinsics are working for 8 bits
我正在尝试使用 _mm256_shuffle_epi8 将 16 位数据打包为 8 位数据,但我得到的结果不是我所期望的。
auto srcData = _mm256_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
__m256i vperm = _mm256_setr_epi8( 0, 2, 4, 6, 8, 10, 12, 14,
16, 18, 20, 22, 24, 26, 28, 30,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1);
auto result = _mm256_shuffle_epi8(srcData, vperm);
我希望结果包含:
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
但我有:
1, 3, 5, 7, 9, 11, 13, 15, 1, 3, 5, 7, 9, 11, 13, 15,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
我肯定误解了 Shuffle 的工作原理。
如果有人能启发我,将不胜感激:)
是的,意料之中。查看 _mm_shuffle_epi8 的文档。 256 位 avx 版本简单地复制了 YMM 寄存器中两个 16 字节值的 128 位指令的行为。
因此您可以随机排列前 16 个值或后 16 个值;但是,您不能在 16 字节边界上随机排列值。 (您会注意到所有超过 16 的数字都是相同的数字减去 16。例如 19->3、31->15 等)。
您需要通过一个额外的步骤来完成此操作。
__m256i vperm = _mm256_setr_epi8( 0, 2, 4, 6, 8, 10, 12, 14,
-1, -1, -1, -1, -1, -1, -1, -1,
0, 2, 4, 6, 8, 10, 12, 14,
-1, -1, -1, -1, -1, -1, -1, -1);
然后用_mm256_permute2f128_si256将第0和第2个字节拉到前128位。
我正在尝试使用 _mm256_shuffle_epi8 将 16 位数据打包为 8 位数据,但我得到的结果不是我所期望的。
auto srcData = _mm256_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
__m256i vperm = _mm256_setr_epi8( 0, 2, 4, 6, 8, 10, 12, 14,
16, 18, 20, 22, 24, 26, 28, 30,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1);
auto result = _mm256_shuffle_epi8(srcData, vperm);
我希望结果包含:
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
但我有:
1, 3, 5, 7, 9, 11, 13, 15, 1, 3, 5, 7, 9, 11, 13, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
我肯定误解了 Shuffle 的工作原理。 如果有人能启发我,将不胜感激:)
是的,意料之中。查看 _mm_shuffle_epi8 的文档。 256 位 avx 版本简单地复制了 YMM 寄存器中两个 16 字节值的 128 位指令的行为。
因此您可以随机排列前 16 个值或后 16 个值;但是,您不能在 16 字节边界上随机排列值。 (您会注意到所有超过 16 的数字都是相同的数字减去 16。例如 19->3、31->15 等)。
您需要通过一个额外的步骤来完成此操作。
__m256i vperm = _mm256_setr_epi8( 0, 2, 4, 6, 8, 10, 12, 14,
-1, -1, -1, -1, -1, -1, -1, -1,
0, 2, 4, 6, 8, 10, 12, 14,
-1, -1, -1, -1, -1, -1, -1, -1);
然后用_mm256_permute2f128_si256将第0和第2个字节拉到前128位。