什么是打包解包和扩展打包数据

What is packed and unpacked and extended packed data

我一直在经历 Intel Intrinsics 并且每个函数都在处理打包、解包或扩展打包的整数、浮点数或双精度数。

这个问题似乎应该在互联网上的某个地方得到解答,但我根本找不到答案。

那个包装的东西是什么?

好吧,我一直在寻找同一个问题的答案,但也没有成功。所以我只能猜测。

英特尔在其 MMX 技术中引入了打包指令和标量指令。比如他们引入了一个函数

__m64 _mm_add_pi8 (__m64 a, __m64 b)

那时候还没有“扩展打包”这回事。唯一的数据类型是 __m64 并且所有操作都适用于整数。 SSE 带来了 128 位寄存器和浮点数运算。但是,SSE2 包含一个 MMX 操作的超集,它对在 128 位寄存器中执行的整数进行操作。例如,

__m128i _mm_add_epi8 (__m128i a, __m128i b)

这里我们第一次看到函数名称中的“ep”(扩展打包)部分。为什么引入它?我相信这是解决名称 _mm_add_pi8 的问题的方法已经被上面列出的MMX指令占用了。SSE/AVX的接口是C语言的,没有函数名的多态性。

对于AVX,英特尔选择了不同的策略,在开始的“_mm”字母之后开始添加寄存器长度,c.f.:

__m256i _mm256_add_epi8 (__m256i a, __m256i b)
__m512i _mm512_add_epi8 (__m512i a, __m512i b)

为什么他们在这里选择“ep”而不是“p”是一个谜,与程序员无关。实际上,他们似乎使用“p”来表示浮点数和双精度数的运算,而“ep”表示整数。

__m128d _mm_add_pd (__m128d a, __m128d b); // "d": function operates on doubles
__m256 _mm256_add_ps (__m256 a, __m256 b); // "s": function operates on floats

也许这可以追溯到从 MMX 到 SSE 的过渡,其中引入了“ep”用于整数运算(MMX 不处理浮点数)并尝试使 AVX 助记符尽可能接近 SSE 助记符

因此,基本上,从程序员的角度来看,“ep”(“扩展打包”)和“p”(“打包”)之间没有区别,因为我们已经知道我们需要的寄存器长度在我们的代码中定位。


至于问题的下一部分,“解包”与“标量”和“打包”属于完全不同的概念类别。这是特定数据重新排列或洗牌的口语化术语,例如旋转或移位。

在像 _mm256_unpackhi_epi16 这样的内在函数名称中使用“epi”的原因是它是一个真正的向量(非标量)函数,作用于 16 位整数元素的向量。请注意,这里的“unpack”属于函数名称中描述其操作的部分(如 mul、add 或 permute),而“s”/“p”/“ep”(标量、打包、扩展打包)属于描述操作模式的部分(“s”的标量,“p”或“ep”的矢量)。

(没有在两个 XMM 寄存器之间运行的标量整数指令,但“si”确实出现在 movd eax, xmm0 的内部名称中:_mm_cvtsi128_si32。有一些类似的内部函数。 )