【问题标题】:Meaning of suffix "x" in intrinsics like "_mm256_set1_epi64x"诸如“_mm256_set1_epi64x”之类的内在函数中后缀“x”的含义
【发布时间】:2017-12-12 20:25:02
【问题描述】:

在某些内在函数中,它们使用后缀 x,例如 _mm256_set1_epi64x。它的意义是什么?作为参考,_mm256_set1_epi32 没有这个后缀。

【问题讨论】:

  • 认为“x”表示内在(和相应的指令)仅在 64 位目标上可用。但我不确定,也无法提供任何证据。这只是我注意到几次的一种模式。您在这里提出的另一个问题确实是题外话。我们不请求外部资源。
  • 我认为这只是当内在函数有两个变体时,一个原始的“历史”变体和一个后续的更有用的变体,例如_mm_set1_epi64 采用 __m64 参数,而 _mm_set1_epi64x 采用 int64_t
  • 许多内在函数的命名非常明显,来自指令助记符,除了很容易忘记 _mm256_permutevar_ps 是 AVX1 车道内 vpermilps 还是车道交叉 AVX2 vpermps。 (它是vpermilpsvpermps_mm256_permutevar8x32_ps)。还有 massive 命名冗余,这会使您的代码膨胀并使其难以阅读。喜欢_mm256_storeu_si256。感谢英特尔,我真的很想在大多数内在函数中输入两次256。但是,如果您不在同一行上嵌套多个内在函数,那么可读性并不可怕。 (即像 asm 一样写)
  • @PaulR:实际上__int64,不一定和int64_t 是一回事。它们可能不兼容别名。一个可能是long 而另一个是long long,因此编译器可以假设int64_t * 没有别名__int64 *。但是,是的,我认为历史是 MMX->SSE2 转换内在函数的 32 位代码采用非 x 名称。
  • @PeterCordes:英特尔和微软似乎更喜欢__int64,而gcc使用long long,大概是因为__int64是非标准的。

标签: x86 vectorization x86-64 simd intrinsics


【解决方案1】:

TL:DR: MMX->SSE2 转换内在函数采用非 x _mm_set/set1_epi64 名称。

这都是基于当前函数名称、已知历史和一些编译器行为的猜测:

第一个英特尔 SIMD 内部函数用于 MMX。 __m64 是 SSE2 __m128i 和 AVX2 __m256i 的 MMX 等效项。当时没有 64 位 x86 CPU,所以最宽的 set 内在函数是 __m64 _mm_set_pi32 (int e1, int e0)。根据内在查找器,movq mm0, rax 仍然没有任何内在。我认为您可以/应该将int64_t 转换为__m64。 (虽然上次我在去年左右进行了实验,但 gcc 或 clang(我忘记了)在优化 MMX asm 方面做得很差。老化的编译器支持是新项目避免使用 MMX 的另一个原因。)

在引入 SSE2 in 2001 时,AMD64 / x86-64 还没有发布,并且在几年内不会得到英特尔的支持。 (当时他们希望IA-64 / Itanium 成为未来并取代x86)。我没有检查旧手册,但我猜当时
__m128i _mm_set1_epi64 (__m64 a) 可用,而
__m128i _mm_set1_epi64x (__int64 a) 可能不可用。 (请注意,__int64 不是来自 <stdint.h>int64_t。但它是 64 位整数类型,无需担心。)

epi 代表扩展(?)压缩整数。 epi 而不是 pi 告诉您它是 SSE 内在函数,而不是 MMX 内在函数。对于从一种元素宽度转换为另一种元素宽度的内在函数,如果能明确标识操作(至少对于我查看的那些),内在函数会使用源宽度。例如_mm_packs_epi32 (packssdw) 或 _mm_unpackhi_epi16 (punpckhwd)。 PMOVZX 需要这两个数字,因为有_mm_cvtepu8_epi32 (pmovzxbd)、_mm_cvtepu8_epi64 (pmovzxbq 等。


编译器当然支持 32 位模式下的 64 位整数,因此英特尔包含用于处理它们的内部函数是有意义的。但是 IIRC,在某些编译器中,64x 内在函数仅在编译 64 位代码时可用64x 仅与 64 位标量整数之间的转换相关,因此您不会找到 _mm_add_epi64x 版本或类似的东西。

_mm256_set1_epi64x 可能仍然存在这种仅 64 位的东西,具体取决于编译器,但无论哪种方式,历史都解释了为什么 64x 而不是 32x

(对不起,我很懒,没有在 Godbolt 上进行实验来检查当前编译器与 -m32。看看你从 int64_t 转换为 __m64 得到什么样的 asm 可能会很有趣并在 32 位代码中使用 _mm_set 内在函数。)

【讨论】:

    猜你喜欢
    • 2016-06-15
    • 2011-05-21
    • 2018-08-15
    • 2017-08-15
    • 2012-07-21
    • 2018-01-09
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多