2

我有一个简单的 asm 代码,它加载 NEON 的 12 个四元寄存器,并具有并行的成对添加指令以及加载指令(以利用双问题能力)。我在这里验证了代码:

http://pulsar.webshaker.net/ccc/sample-d3a7fe78

可以看到,代码大约需要 13 个周期。但是当我在板上加载代码时,加载指令似乎每次加载需要超过一个周期,我验证并发现 VPADAL 需要 1 个周期,但 VLD1 需要超过一个周期。这是为什么?

我已经处理了以下内容:

  1. 地址是 16 字节对齐的。
  2. 在指令中提供了对齐提示vld1.64 {d0, d1} [r0,:128]!
  3. 在某些地方尝试了预加载指令pld [r0, #192],但这似乎增加了周期,而不是实际减少了延迟。

有人可以告诉我我做错了什么,为什么会出现这种延迟?

其他详情:

  • 参考cortex-a8
  • arm-2009q1 交叉编译工具链
  • 汇编中的编码
4

1 回答 1

2

您的代码执行速度比预期的要慢得多,因为它目前正在编写,它导致了管道停顿的完美风暴。在任何具有流水线架构的现代 CPU 上,指令可以在理想条件下在一个周期内执行。理想的条件是指令不等待内存并且没有任何寄存器依赖性。您编写代码的方式不允许延迟从内存读取并使下一条指令依赖于读取的结果。这会导致最糟糕的性能。另外,我不确定您为什么要将成对添加累积到多个寄存器中。尝试这样的事情:

    veor.u16 q12,q12,q12     @ clear accumulated sum
top_of_loop:
    vld1.u16 {q0,q1},[r0,:128]!
    vld1.u16 {q2,q3},[r0,:128]!
    vpadal.u16 q12,q0
    vpadal.u16 q12,q1
    vpadal.u16 q12,q2
    vpadal.u16 q12,q3
    vld1.u16 {q0,q1},[r0,:128]!
    vld1.u16 {q2,q3},[r0,:128]!
    vpadal.u16 q12,q0
    vpadal.u16 q12,q1
    vpadal.u16 q12,q2
    vpadal.u16 q12,q3
    subs r1,r1,#8
    bne top_of_loop

在执行加法之前尝试不同数量的加载指令。关键是您需要在使用目标寄存器之前留出时间进行读取。

注意:使用 Q4-Q7 是有风险的,因为它们是非易失性寄存器。在 Android 上,您会在这些(尤其是 Q4)中随机出现垃圾。

于 2013-02-18T21:21:07.667 回答