用于灰度到 ARGB 转换的 C++ SSE2 或 AVX2 内在函数

标签 c++ intrinsics rgba avx2

我想知道是否要执行 SSE2/AVX2 整数指令或指令序列(或内在函数)以实现以下结果:

给定一行 8 字节像素的形式:

A = {a, b, c, d, e, f, g, h}

有什么方法可以将这些像素加载到包含 8 个 32 位 ARGB 像素的 YMM 寄存器中,以便将初始灰度值广播到每个相应 32 位像素的其他 2 个字节?结果应该是这样的:(0 是 alpha 值)

B = {0aaa, 0bbb, 0ccc, 0ddd, 0eee, 0fff, 0ggg, 0hhh}

我是 vector 扩展的完全初学者,所以我什至不确定如何处理这个问题,或者是否有可能。

如有任何帮助,我们将不胜感激。谢谢!

更新1

感谢您的回答。我仍然有一个问题:

我把这个小例子放在一起,用 VS2015 在 x64 上编译。

int main()
{
    unsigned char* pixels = (unsigned char*)_aligned_malloc(64, 32);
    memset(pixels, 0, 64);

    for (unsigned char i = 0; i < 8; i++)
        pixels[i] = 0xaa + i;

    __m128i grayscalePix = _mm_load_si128((const __m128i*)pixels);
    __m256i rgba = _mm256_cvtepu8_epi32(grayscalePix);
    __m256i mulOperand = _mm256_set1_epi32(0x00010101);

    __m256i result = _mm256_mullo_epi32(rgba, mulOperand);

   _aligned_free(pixels);
    return 0;
}

问题是做了之后

__m256i rgba = mm256_cvtepu8_epi32(grayscalePix)

rgba 只设置了前四个双字。后四位全为0。

英特尔开发人员手册说:

VPMOVZXBD ymm1, xmm2/m64
Zero extend 8 packed 8-bit integers in the low 8 bytes of xmm2/m64 to 8 packed 32-bit integers in ymm1.

我不确定这是有意为之还是我仍然遗漏了什么。

谢谢。

最佳答案

更新:@chtz 的回答是一个更好的主意,使用廉价的 128->256 广播负载而不是 vpmovzx 来提供 vpshufb,从而节省随机端口带宽。


按照 Mark 的建议从 PMOVZX 开始。

但在此之后,PSHUFB (_mm256_shuffle_epi8) 将比 PMULLD 快得多,只是它与 PMOVZX 竞争 shuffle 端口。 (而且它在 channel 内运行,因此您仍然需要 PMOVZX)。

因此,如果您只关心吞吐量,而不关心延迟,那么 _mm256_mullo_epi32 不错。但是,如果延迟很重要,或者如果您的吞吐量瓶颈不是每个 vector 2 个洗牌端口指令,那么 PSHUFB 复制每个像素内的字节应该是最好的。

实际上,即使对于吞吐量,_mm256_mullo_epi32 在 HSW 和 BDW 上也很糟糕:p0 为 2 uops(10c 延迟),因此一个端口为 2 uops。

在 SKL 上,p01 为 2 微指令(10c 延迟),因此它可以维持与 VPMOVZXBD 相同的每个时钟吞吐量。但这是一个额外的 1 uop,使其更容易成为瓶颈。

(VPSHUFB 是 1 uop,1c 延迟,对于端口 5,在所有支持 AVX2 的英特尔 CPU 上。)

关于用于灰度到 ARGB 转换的 C++ SSE2 或 AVX2 内在函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40497227/

相关文章:

c++ - SSE 移位指令在后续指令中导致奇怪的输出 (-1.#IND00)?

c - 使用 ARM Neon 内在函数的 128 位旋转

Python OpenCV - 用透明度覆盖图像

php - 如何向 OpenAI PHP 库提供 RGBA png 文件

c++ - 是否可以创建采用任何类型变量的堆栈类?不止一种

c++ - 加载DLL和直接调用的区别

c++ - "standard output stream"和 "standard output device"有什么区别?

c++ - "is defined"宏检查及其调用必须处于不同的条件下吗?

arm - 从 SSE 到 ARM Neon 的指令转换

css - 一点透明度,更好的阅读体验?