ARM EABI と浮動小数点演算 †前回のベンチマークで,EABI 環境では浮動小数点演算が改善されたことがわかったので,今回はそこらへんを見ていきましょう. プログラム †こんなプログラムを書いて #include <stdio.h> int main ( void ) { double a = 1.0, b = 2.0; printf ( "%f\n", a + b ); return 0; } こんなふうにコンパイルします. $ gcc -mfpu=fpa -O0 floattest.c 浮動小数点演算が最適化されてしまっては意味が無いので,-O0 オプションで最適化を阻止. OABI 環境 †生成された a.out をディスアセンブルしてみます. $ objdump -d a.out a.out: file format elf32-littlearm …(略)… 000083c0 <main>: 83c0: e1a0c00d mov ip, sp 83c4: e92dd810 stmdb sp!, {r4, fp, ip, lr, pc} 83c8: e24cb004 sub fp, ip, #4 ; 0x4 83cc: e24dd010 sub sp, sp, #16 ; 0x10 83d0: e28f3044 add r3, pc, #68 ; 0x44 83d4: e8930018 ldmia r3, {r3, r4} 83d8: e50b3020 str r3, [fp, #-32] 83dc: e50b401c str r4, [fp, #-28] 83e0: e28f303c add r3, pc, #60 ; 0x3c 83e4: e8930018 ldmia r3, {r3, r4} 83e8: e50b3018 str r3, [fp, #-24] 83ec: e50b4014 str r4, [fp, #-20] 83f0: ed1b9108 ldfd f1, [fp, #-32] 83f4: ed1b8106 ldfd f0, [fp, #-24] 83f8: ee010180 adfd f0, f1, f0 83fc: e59f0028 ldr r0, [pc, #40] ; 842c <.text+0x178> 8400: ed2d8102 stfd f0, [sp, #-8]! 8404: e8bd0006 ldmia sp!, {r1, r2} 8408: ebffffa3 bl 829c <.text-0x18> 840c: e3a03000 mov r3, #0 ; 0x0 8410: e1a00003 mov r0, r3 8414: e24bd010 sub sp, fp, #16 ; 0x10 8418: e89da810 ldmia sp, {r4, fp, sp, pc} 841c: 3ff00000 svccc 0x00f00000 ; IMB 8420: 00000000 andeq r0, r0, r0 8424: 40000000 andmi r0, r0, r0 8428: 00000000 andeq r0, r0, r0 842c: 00008524 andeq r8, r0, r4, lsr #10 …(略)… ldfd とか adfd なんていうニーモニックが見えますね. 浮動小数点演算ユニットの無い CPU の場合,
なんて処理を行います. いちいちカーネルモードとユーザモードを行き来するので,オーバヘッドは大きいわけです. EABI 環境の場合 †同様にコンパイルした実行ファイルを同様にディスアセンブルしてみます. $ objdump -d a.out a.out: file format elf32-littlearm …(略)… 00008398 <main>: 8398: e1a0c00d mov ip, sp 839c: e92dd810 push {r4, fp, ip, lr, pc} 83a0: e24cb004 sub fp, ip, #4 ; 0x4 83a4: e24dd014 sub sp, sp, #20 ; 0x14 83a8: e3a03000 mov r3, #0 ; 0x0 83ac: e3a045ff mov r4, #1069547520 ; 0x3fc00000 83b0: e2844603 add r4, r4, #3145728 ; 0x300000 83b4: e50b3024 str r3, [fp, #-36] 83b8: e50b4020 str r4, [fp, #-32] 83bc: e3a03000 mov r3, #0 ; 0x0 83c0: e3a04101 mov r4, #1073741824 ; 0x40000000 83c4: e50b301c str r3, [fp, #-28] 83c8: e50b4018 str r4, [fp, #-24] 83cc: e24b0024 sub r0, fp, #36 ; 0x24 83d0: e8900003 ldm r0, {r0, r1} 83d4: e24b201c sub r2, fp, #28 ; 0x1c 83d8: e892000c ldm r2, {r2, r3} 83dc: eb00000e bl 841c <__adddf3> 83e0: e1a03000 mov r3, r0 83e4: e1a04001 mov r4, r1 83e8: e59f001c ldr r0, [pc, #28] ; 840c <main+0x74> 83ec: e1a02003 mov r2, r3 83f0: e1a03004 mov r3, r4 83f4: ebffffb3 bl 82c8 <_init+0x50> 83f8: e3a03000 mov r3, #0 ; 0x0 83fc: e1a00003 mov r0, r3 8400: e24bd010 sub sp, fp, #16 ; 0x10 8404: e89d6810 ldm sp, {r4, fp, sp, lr} 8408: e12fff1e bx lr 840c: 000088c4 .word 0x000088c4 …(略)… 浮動小数点の足し算は,__adddf3 というルーチンをコールして実行しているようです. で,この __adddf3 は 0000841c <__adddf3>: 841c: e92d4030 push {r4, r5, lr} 8420: e1a04081 lsl r4, r1, #1 8424: e1a05083 lsl r5, r3, #1 8428: e1340005 teq r4, r5 842c: 01300002 teqeq r0, r2 8430: 1194c000 orrsne ip, r4, r0 8434: 1195c002 orrsne ip, r5, r2 8438: 11f0cac4 mvnsne ip, r4, asr #21 843c: 11f0cac5 mvnsne ip, r5, asr #21 8440: 0a00008c beq 8678 <__adddf3+0x25c> 8444: e1a04aa4 lsr r4, r4, #21 8448: e0745aa5 rsbs r5, r4, r5, lsr #21 844c: b2655000 rsblt r5, r5, #0 ; 0x0 8450: da000006 ble 8470 <__adddf3+0x54> …(略)… と,実行プログラムにスタティックリンクされてたりします. つまり,EABI 環境での浮動小数点演算は,ユーザスペースのプログラム内のみで完結しており,カーネルへのスイッチは発生しないことになります. というわけで †先日のベンチマークの結果も納得できましたね. e-mail の文字コード †日本語のe-mail、ISO-2022-JP以外のcharsetを使うのは是か非か(スラッシュドットジャパン) 書き込みを読むと,保守的な人が多いなぁ. 私は「これからは UTF-8 に移行していきましょう」ということでいいと思う. Linux も,ディストロの日本語のデフォルトのロケールが ja_JP.UTF-8 になってきてるというのに,わざわざ JIS にこだわる理由もないだろう. まぁ,手入力の e-mail ならば,ISO-2022-JP 縛りでもそれほど不便はない. が,例えば,ファイルサーバでバックアップの終了を知らせる自動送信メールで文言に
のように UTF-8 縛りのディレクトリ名(Latin-1, 中国語など)が入りうる場合は,UTF-8 で送るのが自然だろう. UTF-8 の対応状況だけど,PC のメーラはほとんど対応しているのだけど,ケータイのメーラが対応していないものが多いのが問題ではある. というわけで,現状で一斉に「UTF-8 に移行しましょう」というのはまだムリかな. |