我正在使用Android上的NDK获取一些重型数字代码,使用LLVM工具链。
我发现如果我在Android.mk中设置LOCAL_ARM_NEON := true
,我的代码速度几乎可以达到50%。我有不编写任何NEON特定的源文件,并且在我的代码中没有NEON内在函数。这是否意味着编译器会自动将NEON指令注入其代码中?
如果是这种情况,那么因为这都是在编译器中生成的,所以我无法通过检查硬件支持来包装NEON代码路径。这里有最好的做法吗?或LOCAL_ARM_NEON := true
从根本上说是不安全的?
进一步的细节:(需要注意的是,我对阅读ARM装配并不是很有经验)
我发现这里较慢的组件非常易读。我发现更快的组装非常难以阅读。 我也不知道它是否有NEON特定指令,因为两个生成的文件似乎都有 EDIT :显然vmul不是NEON特定的。vmul
个this page claims是NEON特定的指令
LOCAL_ARM_NEON
标志)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
LOCAL_ARM_NEON := true
)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}
答案 0 :(得分:0)
好的,我将根据@Michael和@Notlikethat的有用评论自己回答这个问题。那么,我的加速是因为NEON指令(当然)。
设置LOCAL_ARM_NEON := true
似乎允许编译器生成NEON指令,即使对于非.neon文件也是如此。这将使代码不支持不支持NEON的ARMv7。
我认为这给了我两个选择,一个:使用和不使用LOCAL_ARM_NEON := true
编译我的lib版本,并根据CPU是否支持NEON来决定加载哪个版本。
第二个是不设置LOCAL_ARM_NEON := true
,而是将我对性能敏感的代码路径复制到.c.neon
文件中(只允许要使用NEON支持编译的文件。然后,在主文件中,使用cpufeatures
lib检测NEON支持并切换到该文件(如果可用)。