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

AVX-512: _mm512_load vs. standard pointer casting?

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

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

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

I am assuming the only difference between the standard pointer casting and the intrinsic is that the intrinsic will immediately load the data onto a 64 byte register while the pointer casting will wait for a further instruction to do so.

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

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

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

就像两个 int 对象之间的 memcpy 可以优化掉或在方便的时候完成(只要结果就像按源代码顺序完成一样),store/load 内在函数取决于你如何使用它们。就像 + 运算符不必编译为 add 指令一样,_mm_add_ps 也不一定必须使用那些确切的操作数编译为 addps,或者总共添加ps。

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

Is the code above considered dangerous in any way?

没有。普通取消引用仍然是严格别名安全的,因为 __mm* 类型是特殊的。参见