打包和解包以及扩展打包数据

问题描述

我经历过Intel Intrinsics,并且每个函数都在处理已打包或未打包或扩展打包的整数或浮点数或双精度数。

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

那是什么包装物?

解决方法

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

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

__m64 _mm_add_pi8 (__m64 a,__m64 b)

当时还没有“扩展包装”这样的东西。唯一的数据类型是 __m64 并且所有操作都针对整数。 SSE 出现了 128 位寄存器和浮点数运算。但是,SSE2 包括对在 128 位寄存器中执行的整数的 MMX 操作的超集。例如,

__m128i _mm_add_epi8 (__m128i a,__m128i b)

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

对于 AVX,Intel 选择了不同的策略,并在开头的“_mm”字母之后开始添加寄存器长度,参见:

__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 位整数元素的向量。请注意,这里的“解包”属于描述其操作的函数名称部分(如 mul、add 或 permute),而“s”/“p”/“ep”(标量、打包、扩展打包)属于描述操作模式的部分(“s”的标量,“p”或“ep”的向量)。

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