犰狳向量 vec/fvec 的内存对齐
Posted
技术标签:
【中文标题】犰狳向量 vec/fvec 的内存对齐【英文标题】:Memory alignment of Armadillo vectors vec/fvec 【发布时间】:2021-03-08 16:03:22 【问题描述】:我想直接从带有.memptr()
的犰狳矢量数据中加载__m256
。
Armadillo 是否确保数据存储器是 256 位对齐的?如果是这样,那么我只需将.memptr()
返回的浮点/双精度指针转换为__m256
指针并跳过_mm256_load_ps()
,如果它在性能方面有意义的话。
【问题讨论】:
【参考方案1】:犰狳似乎没有在文档中讨论这一点,因此未指定。因此,矢量数据可能无法保证 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 的更多信息。
@Noob: 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*)
。
如果你的数据在运行时恰好是 32 字节对齐的,那么很好,否则硬件会处理它;如果所有 32 个字节都来自同一高速缓存行,则不存在惩罚。但是缓存行拆分对于 OoO exec 隐藏有额外的延迟,并且执行 2 次缓存访问时吞吐量会更差。页面拆分甚至更糟,尤其是在 Skylake 之前的 CPU 上,但对于顺序循环当然很少发生。以上是关于犰狳向量 vec/fvec 的内存对齐的主要内容,如果未能解决你的问题,请参考以下文章