如何使用_mm256_shuffle_epi8对元素进行排序

How to use _mm256_shuffle_epi8 to order elements

提问人:Steffen Roeber 提问时间:9/21/2023 最后编辑:Steffen Roeber 更新时间:9/26/2023 访问量:83

问:

我尝试以下代码。我知道随机播放功能中有一些车道限制。但我不知道如何正确处理它。有人有想法吗?

#include <immintrin.h>

int main() {
  auto vals = _mm256_setr_epi8(
    0, 3, 6, 9,
    1, 4, 7, 10,
    2, 5, 8, 11,
    0, 0, 0, 0,
    12, 15, 18, 21,
    13, 16, 19, 22,
    14, 17, 20, 23,
    0, 0, 0, 0
  );
  auto mask = _mm256_setr_epi8(
    0, 4, 8,
    1, 5, 9,
    2, 6, 10,
    3, 7, 11,
    16, 20, 24,
    17, 21, 25,
    18, 22, 26,
    19, 23, 27,
    -1, -1, -1,
    -1, -1, -1,
    -1, -1);

  auto res = _mm256_shuffle_epi8(vals, mask);
  /*res is:
  0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3 12 17 18 19 20 21 22 23 0 0 0 0 0 0 0 0 0
  but should
  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 0 0 0 0 0 0 0 0 0
  */
  return 0;
}
C++ 内部函数 AVX

评论

1赞 chtz 9/21/2023
_mm256_shuffle_epi8仅在每个 128 位通道内随机播放。您可以将它与或实现您想要的结合使用。根据上下文,可能会有更优雅的解决方案(例如,您从哪里获取数据,以及之后如何处理它)。_mm256_permute4x64_epi64_mm256_permutevar8x32_epi32
0赞 Steffen Roeber 9/21/2023
上下文是从 yuv 到 rgb 的转换 我有一个 mm256 用于 r、g、b 值,并希望结果交错在结果 mm256 寄存器中
1赞 Peter Cordes 9/21/2023
查看 VPSHUFB 上链接的重复项应用了错误的掩码。或者如何更好地将无符号的 8 位数据加载为 16 位?这解释了(与 AVX-512 不同)不是车道交叉,以及对此采取一些措施的选项。如果有一种更有效的方法特定于您正在执行的任何像素随机播放,则可能不是重复的,但是如果您需要帮助,则应更清楚地显示您正在处理的输入和输出格式的布局。(或在转换的此时设置格式。vpshufbvpermb
1赞 chtz 9/21/2023
这个问题确实是重复的,例如,stackoverflow.com/questions/46582438/......如果您想询问 YUV 到 RGB 的转换,请描述您的实际输入和输出格式,以及您对数据执行的操作(或提出一个新问题,我们关闭此问题)。
0赞 chtz 9/25/2023
这回答了你的问题吗?__256i向量的意外_mm256_shuffle_epi

答:

2赞 Soonts 9/26/2023 #1

问题是,不能在向量的 16 字节通道之间移动这些字节。_mm256_shuffle_epi8

一种可能的解决方法是之后的另一个随机指令,这里有一个例子。

__m256i collectRgb( __m256i vals )
{
    // Move the bytes within 16-byte pieces of the vector
    const __m128i gather16 = _mm_setr_epi8(
        0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, -1, -1, -1, -1 );
    const __m256i gatherMask = _mm256_broadcastsi128_si256( gather16 );
    vals = _mm256_shuffle_epi8( vals, gatherMask );

    // Shuffle 4-byte pieces across the complete AVX vector
    const __m256i perm = _mm256_setr_epi32( 0, 1, 2, 4, 5, 6, 7, 7 );
    return _mm256_permutevar8x32_epi32( vals, perm );
}