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

时间:2017-08-16 13:11:32

标签: alignment simd neon arm64

older answer表示aarch64支持未对齐的读/写,并提及性能成本,但不清楚答案是否仅涵盖ALU或SIMD(128位寄存器)操作。

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

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

3 个答案:

答案 0 :(得分:3)

根据 4.6加载/存储对齐部分中的Cortex-A57 Software Optimization Guide,它说:

  

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

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

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

答案 1 :(得分:2)

如果必须拆分加载/存储或使其超过缓存行,则至少需要一个额外的周期。

有一些详尽的表,它们指定Cortex-A8(有序)和Cortex-A9(部分为OoO)的各种对齐方式所需的周期数和寄存器数。例如,具有一个reg的vld1对未对齐访问和64位对齐访问的处罚为1个周期。

Cortex-A55(按顺序)最多可以执行64位加载和128位存储,因此,its optimization manual的3.3节指出,以下情况会产生1个周期的罚款:

  

•跨越64位边界的加载操作
  •跨越128位边界的128位存储操作

根据its optimization guide的第5.4节,Cortex-A75(OoO)会受到以下处罚:

  

•加载跨越64位边界的操作。
  •在AArch64中,所有跨越128位边界的存储。
  •在AArch32中,所有跨越64位边界的存储。

正如吉列尔莫(Guillermo)的回答,A57(OoO)会受到以下处罚:

  

•加载跨越缓存行(64字节)边界的操作
  •存储跨越[128位]边界的操作

我有点怀疑A57不会因为跨越A55和A75而跨越64位边界而受到惩罚。所有这些都有64字节的高速缓存行。他们也应该对跨越缓存行有处罚。最后,请注意,这里有unpredictable behavior for split access crossing pages

从使用Cavium ThunderX进行的一些粗略测试(无性能计数器)来看,罚金似乎接近2个周期,但这可能是背靠背的未对齐负载和循环存储的累加效果


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

vld1.32 {d16-d17}, [r0]    ; no alignment
vld1.32 {d16-d17}, [r0@64] ; 64-bit aligned
vld1.32 {d16-d17}, [r0:64] ; 64 bit-aligned, used by GAS to avoid comment ambiguity

我不知道没有对齐限定符的对齐访问是否比在以AArch32模式运行的最新芯片上使用对齐限定符的访问慢。 ARM的一些旧文档鼓励尽可能使用限定符。 (通过比较,英特尔改进了它们的芯片,使未对齐和对齐的移动在对齐地址时的性能相同。)

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

// MSVC
vld1q_u16_ex(addr, 64);
// GCC:
addr = (uint16_t*)__builtin_assume_aligned(addr, 8);
vld1q_u16(addr);

答案 2 :(得分:0)

在aarch64上不使用对齐提示。它们是透明的。如果指针与数据类型的大小对齐,则性能优势是自动的。

如有疑问,对于GCC / Clang,请在变量声明上使用__attribute__((__aligned__(16)))