AVX-512:_mm512_load 与标准指针转换?

Posted

技术标签:

【中文标题】AVX-512:_mm512_load 与标准指针转换?【英文标题】:AVX-512: _mm512_load vs. standard pointer casting? 【发布时间】:2021-06-22 03:22:08 【问题描述】:

在我的测试中,以下代码似乎执行良好:

double* ptr = _aligned_malloc(sizeof(double) * 8, 64);
__m512d* vect = (__m512d*)ptr;

然而,AVX 提供了功能来做同样的事情 - _mm512_load_pd。上面的代码是否以任何方式被认为是危险的?我假设标准指针转换和内在函数之间的唯一区别是内在函数会立即将数据加载到 64 字节寄存器中,而指针转换将等待进一步的指令来执行此操作。我说的对吗?

【问题讨论】:

【参考方案1】:

我假设标准指针转换和内在函数之间的唯一区别是内在函数将立即将数据加载到 64 字节寄存器中,而指针转换将等待进一步的指令这样做。

不,一点也不。它们完全相同,生成的 asm 没有差异。在大多数编译器上,_mm512_load_pd 只是一个普通的内联函数,它执行类似return *(__m512d *) __P; 的操作——这是 GCC 头文件的精确复制粘贴。因此,负载内在函数实际上已经在这样做了。

__m512ddoubleint 在编译器如何进行寄存器分配以及决定何时实际加载恰好在内存中的 C 对象方面没有根本区别。无论您如何编写它,编译器都可以将负载折叠到稍后的 ALU 指令中(或将其优化掉)。 (并且使用 AVX-512,可能能够折叠 _mm512_set1_pd(x) 广播加载以获取具有匹配元素宽度的指令。)

_mm*_load[u]_* 内在函数可能看起来就像您当时要求单独的加载指令一样,但实际情况并非如此。如果你愿意,这只会让你的 C 看起来更像 asm。

就像两个 int 对象之间的 memcpy 一样,可以在方便的时候优化或完成(只要结果就像按照源顺序完成),因此可以根据如何存储/加载内在函数你使用它们。就像+ 运算符不必编译为add 指令一样,_mm_add_ps 也不必使用这些精确的操作数编译为addps,或者根本不需要编译为addps。

加载/存储内在函数基本上是为了向编译器传达对齐保证(通过 loadu/storeu),并为您处理类型(至少对于 ps 和 pd load[u]/store[u];仍然是整数需要转换指针)。也适用于 AVX-512,以允许屏蔽加载和屏蔽存储。

上面的代码是否被认为是危险的?

没有。因为__mm* 类型是特殊的,所以普通的取消引用仍然是严格别名安全的。见Is `reinterpret_cast`ing between hardware SIMD vector pointer and the corresponding type an undefined behavior?

【讨论】:

以上是关于AVX-512:_mm512_load 与标准指针转换?的主要内容,如果未能解决你的问题,请参考以下文章

AVX512 缺少内在的 _mm512_round_ps

GCC 不断抱怨 AVX512 函数 _mm512_cvt_roundpd_epi64 的“错误:不正确的舍入操作数”

错误:“_mm512_loadu_epi64”未在此范围内声明

使用 AVX512 或 SVML 内在函数将压缩的 16 位整数与掩码相除

使用内在函数将双 SSE2/AVX/AVX512 存储为浮点数的最佳方法

avx512中比较内在指令的不同语义?