当您开始处理 SIMD 指令时,您会注意到内在函数的名称如下
_mm_dp_pd
_mm_mul_pd
仔细查看文档一段时间(或几年)后,您开始注意到一些简写:
d
表示“双精度浮点数”p
是“packed”的缩写(无论这意味着什么......也许是“复数”)dp
表示“点积”然后你认为自己很好,但随后你遇到了类似的乱码
_mm_maddubs_epi16
_mm_mpsadbw_epu8
_mm256_dpwuuds_epi32
然后你开始
mad
(dubs
?)试图弄清楚dpwuuds
到底是什么意思,以及你的大脑到底应该如何在合理的时间内破译它。
是否有任何表格或指南可以帮助普通人破译这些首字母缩略词的含义?
有指导吗?
是的,https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html - 只需在搜索框中输入任何内容即可。 但该指南无法解码命名! 因此,请从内在函数指南中找到相应的 asm 助记符,并在 asm 手册中查找(英特尔 PDF,或在 https://www.felixcloutier.com/x86/)上将其抓取到 HTML 中
您提到的内在名称反映了asm助记符。如果他们无法想出自己的名称,而您必须将其与asm助记符分开记住,那么这就是一种后备。 (我总是根据我想要的 asm 来思考,并编写有望编译成它的 C。)
有时,内在名称比助记符更糟糕、更不明显。
对于扩大或缩小的指令,
_epi16
与 _epi8
的选择通常看起来是任意的。 在这些情况下,我通常必须查找我想要的指令的内部名称。 就像 vpmaddubsw
= _mm_maddubs_epi16
与 pmaddwd
= _mm_madd_epi16
一样。 完全荒谬的是,第一个从 8 扩大到 16(打包乘法加无符号字节有符号字),第二个从 16 扩大到 32。但是一个是 SSE2,一个是 SSSE3,所以它们没有同时命名。 /叹息。
他们是否使用“shuffle”或“permute”也是相当随意的,我们有像
vpermilpd
具有 _mm_permute_pd
(或带有控制向量的 permutevar
)这样的混乱,其中 asm 命名强调它是一个 AVX - 车道洗牌。 但后来 AVX2 出现并添加了粒度小于 128 位的交叉车道洗牌,如 vpermpd
,因此内部命名必须采取一些措施来消除歧义,选择 _mm256_permutex_epi64
,其中 x
表示车道交叉。psadbw
是打包的绝对差和,这是视频编码中的常见操作(搜索相似像素)。 mpsadbw
(https://www.felixcloutier.com/x86/mpsadbw) 是一个多 SAD(将字节偏移量作为立即数),旨在避免单独洗牌的需要。 但它的速度不够快,不值得大多数时间使用。 例如x264 的详尽运动搜索在没有它的情况下会做得更好,我认为部分是通过排除一些组合来使其不是纯粹的暴力,并通过与其他指令进行有效的洗牌。 P 当然是 Packed 的意思,位于助记符的开头,表示整数。 通常,C 内在函数会省略前导 p
(就像 paddb
是 _mm_add_epi8
),但在本例中,p
不是 前导。 所以我们得到 _mm_mpsadbw_epu8
,它只是指令助记符作为名称部分(带有通常的 _mm_
前缀和 _size
后缀)。
p 是“packed”的缩写(无论这意味着什么......也许是“复数”)
Packed 与 Scalar 相对。 像
_mm_add_ss
(添加单个标量)一样,仅更改低位元素,从源操作数复制前 3 个元素。 您通常不会对像 [v]addss
这样的指令使用内在函数,您只需编写编译器不会矢量化的标量代码。 但它们存在,并且如果您在高元素中有一些有趣的东西并且想要在低元素上添加/mul/sqrt 或其他任何内容,它们偶尔会很有用。