【问题标题】:Memory alignment of Armadillo vectors vec/fvec犰狳向量 vec/fvec 的内存对齐
【发布时间】:2021-03-08 16:03:22
【问题描述】:

我想直接从带有.memptr() 的犰狳矢量数据中加载__m256。 Armadillo 是否确保数据存储器是 256 位对齐的?如果是这样,那么我只需将.memptr() 返回的浮点/双精度指针转换为__m256 指针并跳过_mm256_load_ps(),如果它在性能方面有意义的话。

【问题讨论】:

    标签: c++ performance intrinsics armadillo


    【解决方案1】:

    犰狳似乎没有在文档中讨论这一点,因此未指定。因此,矢量数据可能无法保证 32 字节对齐。

    但是,您不需要对齐矢量数据即可将它们加载到 AVX 寄存器中:您可以使用未对齐的加载内在函数_mm256_loadu_ps。 AFAIK,_mm256_load_ps_mm256_loadu_ps 在相对较新的 x86 处理器上的性能大致相同。

    【讨论】:

    • 谢谢。我很好奇当我用reinterpret_castfloat * 转换为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 来实现 loaduIs `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 上,但对于顺序循环当然很少发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多