【发布时间】:2021-03-08 16:03:22
【问题描述】:
我想直接从带有.memptr() 的犰狳矢量数据中加载__m256。
Armadillo 是否确保数据存储器是 256 位对齐的?如果是这样,那么我只需将.memptr() 返回的浮点/双精度指针转换为__m256 指针并跳过_mm256_load_ps(),如果它在性能方面有意义的话。
【问题讨论】:
标签: c++ performance intrinsics armadillo
我想直接从带有.memptr() 的犰狳矢量数据中加载__m256。
Armadillo 是否确保数据存储器是 256 位对齐的?如果是这样,那么我只需将.memptr() 返回的浮点/双精度指针转换为__m256 指针并跳过_mm256_load_ps(),如果它在性能方面有意义的话。
【问题讨论】:
标签: c++ performance intrinsics armadillo
犰狳似乎没有在文档中讨论这一点,因此未指定。因此,矢量数据可能无法保证 32 字节对齐。
但是,您不需要对齐矢量数据即可将它们加载到 AVX 寄存器中:您可以使用未对齐的加载内在函数_mm256_loadu_ps。 AFAIK,_mm256_load_ps 和 _mm256_loadu_ps 在相对较新的 x86 处理器上的性能大致相同。
【讨论】:
reinterpret_cast 将float * 转换为a __m256* 然后简单地取消引用指针时会发生什么,编译器会自动选择_mm256_loadu_ps 吗?
sizeof(Type) 对齐的数据使用reinterpret_cast<Type> 会使您的程序在标准C++ 中格式错误。因此,使用这种转换加载 32 字节未对齐数据会导致未定义的行为。实际上,我建议您即使数据对齐也不要使用reinterpret_cast。您可以找到有关 here 的更多信息。
alignof(__m256) == 32,所以 deref 等价于load,而不是loadu。有趣的事实:像 GNU C 这样的编译器可以使用 __attribute__((aligned(1),may_alias,vector_size(32))) 类型的 deref 来实现 loadu。 Is `reinterpret_cast`ing between hardware SIMD vector pointer and the corresponding type an undefined behavior?。对于整数数据,您通常需要某种类型的强制转换(因为英特尔恼人地将内在函数定义为采用 __m256i* 而不是 void*),但是对于浮点数,只需使用 _mm256_loadu_ps(const float*)。