c++ - 使用 SIMD : AVX2 version mixes up the order 将 8 位解包到 16 位

标签 c++ simd sse avx2

我正在尝试使用 SSE2 用零解压缩文本,并将其扩展到 AVX2。这就是我的意思:
假设您有一些这样的文本:abcd我正在尝试使用 SSE2 来解包 abcd进入 a\0b\0c\0d . \0是零。这当然适用于 16 个字符而不是 4 个。
我能够使用此代码(忽略 C 样式转换)来做到这一点:

__m128i chunk = _mm_loadu_si128((__m128i const*) src); // Load 16 bytes from memory

__m128i half = _mm_unpacklo_epi8(chunk, _mm_setzero_si128()); // Unpack lower 8 bytes with zeros
_mm_storeu_si128((__m128i*) dst, half); // Write to destination

half = _mm_unpackhi_epi8(chunk, _mm_setzero_si128()); // Unpack higher 8 bytes with zeros
_mm_storeu_si128((__m128i*) (dst + 16), half); // Write to destination
这很好用,但我正在尝试将代码转换为 AVX2,因此我可以一次处理 32 个字节。但是,我在解压低字节时遇到了麻烦。
这是我用于 AVX2 的代码:
__m256i chunk = _mm256_loadu_si256((__m256i const*) src); // Load 32 bytes from memory

__m256i half = _mm256_unpacklo_epi8(chunk, _mm256_setzero_si256()); // Unpack lower 16 bytes with zeros
_mm256_storeu_si256((__m256i*) dst, half); // Write to destination

half = _mm256_unpackhi_epi8(chunk, _mm256_setzero_si256()); // Unpack higher 16 bytes with zeros
_mm256_storeu_si256((__m256i*) (dst + 32), half); // Write to destination
问题是,_mm256_unpacklo_epi8指令似乎每转换 8 个字节就跳过 8 个字节。例如这段文字(末尾的“fr”是有意的):
Permission is hereby granted, fr
被转换成
Permissireby graon is hented, fr
每 8 个字节 _mm256_unpacklo_epi8 , 处理, 8 个字节被跳过。
我在这里做错了什么?
任何帮助将不胜感激。

最佳答案

正如我所看到的,@PeterCordes 已经收到了正确的答案。不过我想用小的辅助函数来补充它:

template <int part> inline __m256i Cvt8uTo16u(__m256i a)
{
    return _mm256_cvtepu8_epi16(_mm256_extractf128_si256(a, part));
}

关于c++ - 使用 SIMD : AVX2 version mixes up the order 将 8 位解包到 16 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68822791/

相关文章:

c++ - 在 C++ 中读取文件并处理可能的错误的可移植方法

c++ - C++ 中的 Sizeof 以及如何计算指针长度?

c - 如何将 32 位 float 转换为 8 位有符号字符? (4 :1 packing of int32 to int8 __m256i)

objective-c - 解释 Metal 和 SIMD 中的不同类型

x86 - 8 个打包的 32 位 float 的水平总和

c++ - 如何将 2 个 16 位 vector 相乘并将结果存储在 sse 中的 32 位 vector 中?

c++ - 为什么 hash<const char*> 适用于字符串而不适用于字符串变量?

c++ - 两个类(class)可以成为 friend 吗?

C++ SIMD : Store uint64_t value after bitwise and operation

c - 使用 SSE Intrinsics 计算长度和差异的浮点 x、y、z 数组上的循环向量化