使用 AVX 内部函数进行转换

Posted

技术标签:

【中文标题】使用 AVX 内部函数进行转换【英文标题】:Casting with AVX intrinsics 【发布时间】:2018-04-30 22:49:45 【问题描述】:

使用 AVX2 有两种投射方式:

__m256i b = ...set register...
auto c = (__m256d)b; // version 1
auto d = _mm256_castsi256_pd(b); // version 2

我认为这两个应该给出相同的结果。来自 Intel 的 official manual 表示版本 2 的运行时延迟为零。我可以在零延迟假设下使用版本 1 吗?此外,我可以假设从任何到版本 1 的任何寄存器类型的转换都是零延迟。

【问题讨论】:

如果您对可移植性感兴趣,那么最好使用版本 2 - 最麻烦的编译器是 MSVC,我认为它会抱怨版本 1。(我已经有一段时间没有解决问题了不过这个,所以你可能想自己检查一下你打算支持的编译器)。 谢谢 - 请记住这一点。 另外,我确实试用了版本 1,它在我的实验中似乎有一些开销。尽管如此,最好有一个更技术和更完整的答案。 您为尝试版本 1 做了哪些实验?我认为任何接受它的编译器都会将其视为像版本 2 一样的重新解释转换,但错过优化总是有可能的。尽管您的实验有缺陷,但更有可能。你检查编译器的 asm 输出了吗? (无论如何,好问题。我认为答案是版本 2 始终被推荐用于可移植性,但没有理由期望任何一个版本都可以组装任何额外的指令来处理这些位。) 这听起来过于复杂。您更有可能通过在整数比较之间使用 FP shuffle 或混合在您使用的任何 CPU 上引入额外的旁路延迟延迟,反之亦然。 (英特尔 SnB 系列 CPU 通常不会对 shuffle 进行跨域惩罚,但对 blends 则有。agner.org/optimize)。或者您使用的不同 shuffle 以不同方式优化或具有不同的吞吐量!绝对听起来您测量的差异不是由于转换本身,除非编译器错过了转换优化。 【参考方案1】:

至少在 gcc 中,'version 1' 正是 'version 2' 的实现方式:

extern __inline __m256d __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm256_castsi256_pd (__m256i __A)

  return (__m256d) __A;

https://github.com/gcc-mirror/gcc/blob/gcc-8_1_0-release/gcc/config/i386/avxintrin.h#L1440

Clang 本质上是相同的: https://github.com/llvm-mirror/clang/blob/release_60/lib/Headers/avxintrin.h#L4449

我没有寻找其他编译器,但我也不认为那里会发生任何神奇的事情。

不过,为了可移植性和可读性,我建议使用_mm256_castsi256_pd,或者如果写得太多,请将其封装到您自己的(内联)函数中。如果您需要重构它们,C 样式转换在源代码中相对难以找到。

【讨论】:

以上是关于使用 AVX 内部函数进行转换的主要内容,如果未能解决你的问题,请参考以下文章

强制 AVX 内部函数改为使用 SSE 指令

通过使用 AVX 内部函数重写来提高 math.h 函数的性能

将 SSE2 和 AVX 内部函数与不同的编译器混合

AVX 类型的 C++ 内部函数的参考和在线资源 [关闭]

我可以使用内在函数加速类型转换吗?

使用 sse 和 avx 内在函数将一组打包的单曲添加到一个值中