在aarch64上未对齐的SIMD加载/存储的性能

hsi*_*nen 5 simd alignment neon arm64

一个旧的回答表明,aarch64支持不对齐的读/写,并有一个关于性能成本提及,但目前还不清楚,如果回答的都是关于ALU和SIMD(128位寄存器)操作了。

相对于对齐的128位NEON加载和存储,在aarch64上未对齐的128位NEON加载和存储要慢多少(如果有的话)?

是否有针对未对齐SIMD加载和存储的单独指令(如SSE2的情况),或者已知对齐的加载/存储的指令与潜在未对齐的加载/存储的指令相同?

Zac*_*chB 7

如果加载/存储必须被分割或跨越缓存线,则至少需要一个额外的周期。

\n\n

有详尽的表格指定了各种对齐所需的周期数以及Cortex-A8(按顺序)和Cortex-A9(部分 OoO)的寄存器数量。例如,vld1对于 1 个寄存器,未对齐访问与 64 位对齐访问相比会产生 1 个周期的损失。

\n\n

Cortex-A55(按顺序)最多可进行 64 位加载和 128 位存储,因此,其优化手册的第 3.3 节指出,会因以下原因而产生 1 周期损失:

\n\n
\n

\xe2\x80\xa2 跨越 64 位边界的加载操作
\n \xe2\x80\xa2 跨越 128 位边界的 128 位存储操作

\n
\n\n

Cortex-A75 (OoO) 根据其优化指南第 5.4 节对以下方面进行处罚:

\n\n
\n

\xe2\x80\xa2 跨越 64 位边界的加载操作。
\n \xe2\x80\xa2 在 AArch64 中,所有跨越 128 位边界的存储。
\n \xe2\x80\xa2 在 AArch32 中,所有跨越 64 位边界的存储。

\n
\n\n

正如 Guillermo 的回答所示,A57 (OoO) 的惩罚是:

\n\n
\n

\xe2\x80\xa2 跨越缓存行(64 字节)边界的加载操作
\n \xe2\x80\xa2 跨越 [128 位] 边界的存储操作

\n
\n\n

鉴于 A55 和 A75 有跨越 64 位边界的惩罚,我有点怀疑 A57 没有。所有这些都有 64 字节缓存行;他们也应该因跨越缓存线而受到惩罚。最后,请注意,跨页拆分访问存在不可预测的行为不可预测的行为。

\n\n

从使用 Cavium ThunderX 进行的一些粗略测试(没有性能计数器)来看,似乎更接近 2 个周期的惩罚,但这可能是循环中连续未对齐加载和存储的附加效果。

\n\n
\n\n

AArch64 NEON 指令不区分对齐和未对齐(例如参见LD1 )。对于 AArch32 NEON,对齐方式在寻址 ( VLDn ) 中静态指定:

\n\n
vld1.32 {d16-d17}, [r0]    ; no alignment\nvld1.32 {d16-d17}, [r0@64] ; 64-bit aligned\nvld1.32 {d16-d17}, [r0:64] ; 64 bit-aligned, used by GAS to avoid comment ambiguity\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不知道在 AArch32 模式下运行的最新芯片上,不带对齐限定符的对齐访问是否比使用对齐限定符的访问执行得慢。ARM 的一些旧文档鼓励尽可能使用限定符。(相比之下,英特尔改进了他们的芯片,使未对齐和对齐的移动在地址对齐时执行相同的操作。)

\n\n

如果您使用内在函数,MSVC 具有_ex接受对齐的 - 后缀变体。让 GCC 发出对齐限定符的可靠方法是使用__builtin_assume_aligned

\n\n
// MSVC\nvld1q_u16_ex(addr, 64);\n// GCC:\naddr = (uint16_t*)__builtin_assume_aligned(addr, 8);\nvld1q_u16(addr);\n
Run Code Online (Sandbox Code Playgroud)\n


Gui*_*rmo 6

根据Cortex-A57 软件优化指南4.6加载/存储对齐,它说:

ARMv8-A 架构允许任意对齐多种类型的加载和存储访问。Cortex-A57 处理器可以处理大多数未对齐的访问,而不会降低性能。但是,在某些情况下会减少带宽或导致额外的延迟,如下所述:

  • 跨越缓存行(64 字节)边界的加载操作
  • 存储跨越 16 字节边界的操作

因此,它可能取决于您使用的处理器,无序(A57、A72、A-72、A-75)或有序(A-35、A-53、A-55)。我没有找到任何针对有序处理器的优化指南,但是它们确实有一个硬件性能计数器,您可以使用它来检查未对齐指令的数量是否会影响性能:

    0xOF_UNALIGNED_LDST_RETIRED Unaligned load-store
Run Code Online (Sandbox Code Playgroud)

这可以与perf工具一起使用。

AArch64 中没有针对未对齐访问的特殊说明。