使用 AVX2 将 8 位从 32 位值 (__m256i) 解压缩到__m256的最快方法
Fastest way to unpack 8bit from 32bit values (__m256i) into __m256 with AVX2
我有一个名为A
的array
,其中包含32个unsigned char
值。
我想用这个规则将这些值解压缩在 4 个__m256
变量中,假设我们有一个从 0 到 31 的索引,关于A
中的所有值,解压缩的 4 个变量将具有以下值:
B_0 = A[0], A[4], A[8], A[12], A[16], A[20], A[24], A[28]
B_1 = A[1], A[5], A[9], A[13], A[17], A[21], A[25], A[29]
B_2 = A[2], A[6], A[10], A[14], A[18], A[22], A[26], A[30]
B_3 = A[3], A[7], A[11], A[15], A[19], A[23], A[27], A[31]
为此,我有以下代码:
const auto mask = _mm256_set1_epi32( 0x000000FF );
...
const auto A_values = _mm256_i32gather_epi32(reinterpret_cast<const int*>(A.data(), A_positions.values_, 4);
// This code bellow is equivalent to B_0 = static_cast<float>((A_value >> 24) & 0x000000FF)
const auto B_0 = _mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srai_epi32(A_values, 24), mask));
const auto B_1 = _mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srai_epi32(A_values, 16), mask));
const auto B_2 = _mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srai_epi32(A_values, 8), mask));
const auto B_3 = _mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srai_epi32(A_values, 0), mask));
这很好用,但我想知道是否有一些更快的方法可以做到这一点,特别是关于我用来检索值的右移和运算符。
另外,为了澄清起见,我说array
A
的大小为 32,但事实并非如此,这个数组包含更多的值,我需要从不同的位置访问它的元素(但总是来自 4 个uint8_t
块(,这就是我使用_mm256_i32gather_epi23
来检索这些值的原因。为了简单起见,我只是在此示例中限制array
大小。
移位/掩码可以组合成一个vpshufb
。当然,这意味着需要担心洗牌面具,这些面具必须来自某个地方。如果它们可以留在寄存器中,那没什么大不了的,如果必须加载它们,可能会杀死这种技术。
这似乎是对英特尔的优化,因为这种转变的 recip.throughput 为 0.5 和 AND 0.33,这比洗牌得到的 1 要好(具有两个洗牌单元的英特尔处理器不支持 AVX2,因此它们不相关,因此洗牌转到 P5(。它仍然较少的μops,因此在其他代码的上下文中,它可能值得也可能不值得做,这取决于瓶颈是什么。如果代码的其余部分只使用 P01(FP SIMD 的典型特征(,则将 μops 移动到 P5 可能是个好主意。
在锐龙上,它通常更好,因为矢量移位在那里的吞吐量较低。256bvpsrad
生成 2 μops,两者都必须转到端口 2(然后vpand
还有两个 μop,但它们可以转到四个 alu 端口中的任何一个(,256bvpshufb
生成 2 μops 可以转到端口 1 和 2。另一方面,Ryzen 上的聚集是如此糟糕,以至于与由此产生的大量微运算相比,这一切都只是噪音。你可以手动收集,但它仍然有很多μops,他们可能会去P12,这使得这种技术很糟糕。
总之,我不能告诉你这是否真的更快,这取决于。
- 使用C++进行运行长度解压缩
- C++ 如何将数组值解压缩为函数参数
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 在 Qt(C++) 中使用 QProcess 解压缩 - 提取目录问题
- 浏览压缩文件与游览解压缩它们
- 如何在C++向量中解压缩多个值
- 解压缩 C 样式数组以及C++中的参数包
- 如何在 cpp 中解压缩数字,如果它们是使用 struct.pack(fmt, v1, v2, ..) 打包在 pyth
- 如何使用 Poco::ZIP 压缩/解压缩 zip 文件
- 在编译时解压缩数组扩展数据块 (C++11/14)
- 使用 RtMidi 解压缩 Midi 时间码
- 将参数包解压缩到 std::initializer_list?
- 解压缩可变模板参数
- 解压缩附加的压缩字符串
- 使用 AVX2 将 8 位从 32 位值 (__m256i) 解压缩到__m256的最快方法
- C++宏解压缩并加入
- 解压缩串联的 zlib 流而不读取下一个字节
- 解压缩位大小不能被 8 整除的值流
- 为流运算符返回代理类时解压缩参数
- 如何在 Node.js 中解压缩 c# 打包结构