Nexus 7 の Ubuntu 13.04 は armhf (hard-float) です。
Android NDK は softfp なので、
Ubuntu の方が関数呼び出しが効率化されていると考えられます。
比べてみました。
// 元のソース float func2( float a, float b, float c ) { return a * b + c; } float func3( float a, float b, float c ) { return a + b - c; } float func1( float a, float b ) { return a * b + a; }
↓gcc によるコンパイル結果 (softfp)
// -marm -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3 fmsr s14, r0 fmsr s13, r2 fmsr s15, r1 fmacs s13, s14, s15 fmrs r0, s13 bx lr fmsr s13, r0 fmsr s14, r1 fadds s15, s13, s14 fmsr s13, r2 fsubs s13, s15, s13 fmrs r0, s13 bx lr fmsr s13, r0 fmsr s15, r1 fmacs s13, s13, s15 fmrs r0, s13 bx lr
soft といっても浮動小数点演算をエミュレーション実行しているわけではなく、
上記のように VFP や NEON 等の HW 演算ユニットが使われています。
あくまで ABI (Calling Convention) の話で、関数の呼び出し時のレジスタの
使われ方が異なります。
softfp の場合は FPU (VFP) が無い場合 (soft) と互換性が取れるように、
レジスタ渡しの場合に浮動小数点値も整数レジスタ(r)に入ります。
上の結果でも、毎回整数レジスタ(r)に入った引数を VFP レジスタ(s)へ
コピーしていることがわかります。
-mfloat-abi=hard を指定すると↓下記のように不要な転送が無くなりました。
引数や戻り値としてそのまま VFP レジスタ(s)が使われています。
// -marm -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3 fmacs s2, s0, s1 fcpys s0, s2 bx lr fadds s0, s0, s1 fsubs s0, s0, s2 bx lr fmacs s0, s0, s1 bx lr
↓さらに vfpv4 を指定すると、fmacs の代わりに vfma が使われていることがわかります。
// -marm -march=armv7-a -mfloat-abi=hard -mfpu=vfpv4 vfma.f32 s2, s0, s1 fcpys s0, s2 bx lr fadds s0, s0, s1 fsubs s0, s0, s2 bx lr vfma.f32 s0, s0, s1 bx lr
NEON 命令も試してみました。
// 元のソース #includefloat32x4_t func4( float32x4_t a, float32x4_t b ) { return a * b + a; }
-ffast-math を付けると neon 命令に変換できます。
↓softfp では 128bit x2 の値をレジスタだけで渡すことができません。
2つ目の引数が stack に入っています。
// -marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon -ffast-math vmov d16, r0, r1 @ v4sf vmov d17, r2, r3 vld1.64 {d18-d19}, [sp:64] vmla.f32 q8, q9, q8 vmov r0, r1, d16 @ v4sf vmov r2, r3, d17 bx lr
↓hard の場合すべてレジスタで受け渡し可能となります。
// -marm -march=armv7-a -mfloat-abi=hard -mfpu=neon -ffast-math vmla.f32 q0, q1, q0 bx lr
以上より hard-float の場合に下記の 2つのメリットあるようです。
(他にもあるかもしれません)
・整数レジスタとの転送が不要となる
・引数として利用可能なレジスタの個数が増える
具体的な速度は測定していませんが、より高速に実行できると考えられます。
Android NDK だけでなく iOS の新しいアーキテクチャ armv7s でも softfp
相当となっているようです。
関連エントリ
・Nexus 7 上に開発環境をつくる (3) Ubuntu
・Nexus 7 上に開発環境をつくる (2) Bluetooth と OpenGL ES 2.0
・Android Tablet Nexus 7 上に開発環境をつくる (Ubuntu)