我有一个简单的asm代码,它加载12个NEON的四个寄存器,并且具有并行的成对添加指令以及加载指令(以利用双重发布功能)。我在这里验证了代码:
http://pulsar.webshaker.net/ccc/sample-d3a7fe78
可以看出,代码大约需要13个周期。但是当我在板上加载代码时,加载指令似乎每个负载需要多个周期,我验证并发现VPADAL按照规定进行了1个周期,但VLD1需要多个周期。那是为什么?
我已经处理了以下事项:
vld1.64 {d0, d1} [r0,:128]!
pld [r0, #192]
,但似乎会增加周期,而不是实际减少延迟。有人能告诉我我做错了什么,为什么会出现这种延迟?
其他细节:
答案 0 :(得分:1)
您的代码执行速度比预期慢得多,因为它目前正在编写,导致管道停滞的完美风暴。在任何具有流水线架构的现代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)。