带有 __256i 向量的意外 _mm256_shuffle_epi

sve*_*evs 1 c++ intrinsics avx avx2

我在使用 AVX2 进行图像转换时看到了这个很棒的答案__m128i,并且认为我会尝试使用 AVX2 来看看是否可以更快地获得它。该任务是获取输入 RGB 图像并将其转换为 RGBA(注意另一个问题是 BGRA,但这并不是一个很大的区别......)。

如果需要,我可以包含更多代码,但是这些东西变得非常冗长,而且我陷入了看似非常简单的事情。假设对于此代码,所有内容都是 32 字节对齐、使用-mavx2等进行编译。

给定输入uint8_t *sourceRGB 和输出uint8_t *destinationRGBA,它会像这样(只是尝试用条纹填充图像的四分之一 [因为这是矢量土地])。

#include <immintrin.h>
__m256i *src = (__m256i *) source;
__m256i *dest = (__m256i *) destination;

// for this particular image
unsigned width = 640;
unsigned height = 480;
unsigned unroll_N = (width * height) / 32;
for(unsigned idx = 0; idx < unroll_N; ++idx) {
    // Load first portion and fill all of dest[0]
    __m256i src_0 = src[0];
    __m256i tmp_0 = _mm256_shuffle_epi8(src_0,
        _mm256_set_epi8(
            0x80, 23, 22, 21,// A07 B07 G07 R07
            0x80, 20, 19, 18,// A06 B06 G06 R06
            0x80, 17, 16, 15,// A05 B05 G05 R05
            0x80, 14, 13, 12,// A04 B04 G04 R04
            0x80, 11, 10,  9,// A03 B03 G03 R03
            0x80,  8,  7,  6,// A02 B02 G02 R02
            0x80,  5,  4,  3,// A01 B01 G01 R01
            0x80,  2,  1,  0 // A00 B00 G00 R00
        )
    );

    dest[0] = tmp_0;

    // move the input / output pointers forward
    src  += 3;
    dest += 4;
}// end for
Run Code Online (Sandbox Code Playgroud)

这实际上根本不起作用。每个“季度”都会出现条纹。

  • 我的理解是0x80应该用于0x00在蒙版中 创建
    • 那里的值是什么并不重要(它是 alpha 通道,在实际代码中它会OR0xff链接的答案一样)。
  • 04它似乎与行有关07,如果我让它们全部0x80离开00-03不一致就会消失。
    • 但当然,我不会复制我需要的所有内容。

我在这里缺少什么?就像我可能用完了寄存器之类的吗?我会对此感到非常惊讶...

包含随机播放两部分的图像

使用

_mm256_set_epi8(
    // 0x80, 23, 22, 21,// A07 B07 G07 R07
    // 0x80, 20, 19, 18,// A06 B06 G06 R06
    // 0x80, 17, 16, 15,// A05 B05 G05 R05
    // 0x80, 14, 13, 12,// A04 B04 G04 R04
    0x80, 0x80, 0x80, 0x80,
    0x80, 0x80, 0x80, 0x80,
    0x80, 0x80, 0x80, 0x80,
    0x80, 0x80, 0x80, 0x80,
    0x80, 11, 10,  9,// A03 B03 G03 R03
    0x80,  8,  7,  6,// A02 B02 G02 R02
    0x80,  5,  4,  3,// A01 B01 G01 R01
    0x80,  2,  1,  0 // A00 B00 G00 R00
)
Run Code Online (Sandbox Code Playgroud)

使用上面的随机播放代替

har*_*old 6

_mm256_shuffle_epi8工作方式类似于并排两次_mm_shuffle_epi8,而不是像更有用(但可能更高延迟)的全角随机播放,可以将任何字节放在任何地方。这是来自www.officedaytime.com/simd512e的图表:

VPshufb

AVX512VBMI 具有新的字节粒度混洗,例如vpermb可以跨通道的混洗,但当前处理器尚不支持该指令集扩展。