Optimization 为什么在没有特殊代码路径的情况下,设置LOCAL_ARM_NEON会使速度加倍?

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根本不安全

我使用Android上的NDK来编写一些繁重的数字代码,使用LLVM工具链

我发现,如果我在我的Android.mk中设置
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}