Optimization 为什么在没有特殊代码路径的情况下,设置LOCAL_ARM_NEON会使速度加倍?
我使用Android上的NDK来编写一些繁重的数字代码,使用LLVM工具链 我发现,如果我在我的Android.mk中设置Optimization 为什么在没有特殊代码路径的情况下,设置LOCAL_ARM_NEON会使速度加倍?,optimization,assembly,android-ndk,arm,neon,Optimization,Assembly,Android Ndk,Arm,Neon,我使用Android上的NDK来编写一些繁重的数字代码,使用LLVM工具链 我发现,如果我在我的Android.mk中设置LOCAL\u ARM\u NEON:=true,我的代码的速度几乎会提高50%。我没有编写任何特定于NEON的源文件,代码中也没有NEON内部函数。这是否意味着编译器将自动向其代码中注入霓虹灯指令 如果是这种情况,那么因为这些都是在编译器中生成的,所以我不能用检查硬件支持来包装NEON代码路径。这里有最佳实践吗?或者LOCAL\u ARM\u NEON:=true根本不安全
LOCAL\u ARM\u NEON:=true
,我的代码的速度几乎会提高50%。我没有编写任何特定于NEON的源文件,代码中也没有NEON内部函数。这是否意味着编译器将自动向其代码中注入霓虹灯指令
如果是这种情况,那么因为这些都是在编译器中生成的,所以我不能用检查硬件支持来包装NEON代码路径。这里有最佳实践吗?或者LOCAL\u ARM\u NEON:=true
根本不安全
进一步的细节:(注意,我不是很有经验阅读臂装配)
生成的程序集的比较。
我发现这里较慢的程序集非常可读。我发现读更快的汇编非常有挑战性。我也不知道它是否有特定于霓虹灯的指令,因为两个生成的文件似乎都有特定于霓虹灯的指令:显然,vmul不是特定于霓虹灯的
慢速代码(不设置本地\u ARM\u NEON
标志)
好的,我将根据@Michael和@Notlikethat的有用评论自己回答这个问题。我的加速是因为霓虹灯的指示(当然) 似乎设置
LOCAL\u ARM\u NEON:=true
允许编译器生成NEON指令,即使对于非.NEON文件也是如此。这将使代码不可移植到不支持NEON的ARMv7
我认为这给了我两个选择,一个是:编译一个lib版本,有和没有LOCAL\u ARM\u NEON:=true
,并根据CPU是否支持NEON在Java中决定加载哪个版本
第二种方法是不设置
LOCAL\u ARM\u NEON:=true
,而是将性能敏感的代码路径复制到.c.NEON
文件中(这将只允许使用NEON支持编译该文件。然后,在主文件中,使用cpufeatures
lib检测NEON支持,并切换到该文件(如果可用)。“两个生成的文件似乎都有vmul指令,本页声称这些指令是NEON特定的”V{N}MUL cond}.F32{Sd,}Sn,Sm
是一条VFP指令(请参阅)@Michael我明白了:我被这一页弄糊涂了,它说:“表15显示了霓虹灯指令的摘要。这些指令在VFP中不可用。”事实上,只要看看寄存器的使用就知道了:简单的标量循环在s
上运行(单个)寄存器,即一次一个32位浮点。第二个循环在q
(四元)寄存器上运行-一次四个浮点-因为它是自动矢量化的。
00000000 <_dotProduct>:
0: ed9f 0a08 vldr s0, [pc, #32] ; 24 <_dotProduct+0x24>
4: 2a01 cmp r2, #1
6: bfb8 it lt
8: 4770 bxlt lr
a: ed90 1a00 vldr s2, [r0]
e: 3004 adds r0, #4
10: ed91 2a00 vldr s4, [r1]
14: 3104 adds r1, #4
16: 3a01 subs r2, #1
18: ee22 1a01 vmul.f32 s2, s4, s2
1c: ee31 0a00 vadd.f32 s0, s2, s0
20: d1f3 bne.n a <_dotProduct+0xa>
22: 4770 bx lr
24: 00000000 .word 0x00000000
00000000 <_dotProduct>:
0: b510 push {r4, lr}
2: 2a01 cmp r2, #1
4: db1b blt.n 3e <_dotProduct+0x3e>
6: 2a00 cmp r2, #0
8: d01c beq.n 44 <_dotProduct+0x44>
a: efc0 0050 vmov.i32 q8, #0 ; 0x00000000
e: f022 0c03 bic.w ip, r2, #3
12: f1bc 0f00 cmp.w ip, #0
16: d01a beq.n 4e <_dotProduct+0x4e>
18: 46e6 mov lr, ip
1a: 460b mov r3, r1
1c: 4604 mov r4, r0
1e: f964 2a8f vld1.32 {d18-d19}, [r4]
22: f1be 0e04 subs.w lr, lr, #4
26: f104 0410 add.w r4, r4, #16
2a: f963 4a8f vld1.32 {d20-d21}, [r3]
2e: f103 0310 add.w r3, r3, #16
32: ff44 2df2 vmul.f32 q9, q10, q9
36: ef42 0de0 vadd.f32 q8, q9, q8
3a: d1f0 bne.n 1e <_dotProduct+0x1e>
3c: e009 b.n 52 <_dotProduct+0x52>
3e: ef80 0010 vmov.i32 d0, #0 ; 0x00000000
42: bd10 pop {r4, pc}
44: ef80 0010 vmov.i32 d0, #0 ; 0x00000000
48: f04f 0c00 mov.w ip, #0
4c: e00b b.n 66 <_dotProduct+0x66>
4e: f04f 0c00 mov.w ip, #0
52: eff0 28e0 vext.8 q9, q8, q8, #8
56: 4594 cmp ip, r2
58: ef40 0de2 vadd.f32 q8, q8, q9
5c: fffc 2c60 vdup.32 q9, d16[1]
60: ef00 0de2 vadd.f32 q0, q8, q9
64: d011 beq.n 8a <_dotProduct+0x8a>
66: eb01 018c add.w r1, r1, ip, lsl #2
6a: eb00 008c add.w r0, r0, ip, lsl #2
6e: eba2 020c sub.w r2, r2, ip
72: ed90 2a00 vldr s4, [r0]
76: 3004 adds r0, #4
78: ed91 3a00 vldr s6, [r1]
7c: 3104 adds r1, #4
7e: 3a01 subs r2, #1
80: ff43 0d12 vmul.f32 d16, d3, d2
84: ef00 0d80 vadd.f32 d0, d16, d0
88: d1f3 bne.n 72 <_dotProduct+0x72>
8a: bd10 pop {r4, pc}