CodeSourceryでNEON演算

とりあえず更新をさぼってたけど
その間、BeagleBoardAndroid1.6r1.2入れたりUbuntu9.10いれたりして遊んでました。


そして今日ARMフォーラムへ行ってきたら、なんかARMのNEON演算の講演が二つもあって
しかもそのうち1つの講演はBeagleBoardNEON演算簡単にできますよ的な内容だったので
感化されてNEON演算をちょっとさわってみたくなりました。


なんとなく講演聞いてみて、NEON演算はIntelで言うMMXとかSSEと同じメディア演算SIMDなんだな、ということを理解(いまさら
とりあえず積和演算をコンパイルしてアセンブラを確認してみる。
どうもvmulとかvaddとか接頭語がvなのがNEON命令らしい。

$ cat neon.c
float a[256], b[256], c[256];

foo(int x) { int i; for (i = 0; i < 256; i++) { a[i] = x * b[i] + c[i]; } }

$ arm-none-linux-gnueabi-gcc -S -O3 -march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize neon.c

$ cat neon.s
.cpu cortex-a8
.eabi_attribute 27, 3
.fpu neon
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 2
.eabi_attribute 18, 4
.file "neon2.c"
.text
.align 2
.global foo
.type foo, %function
foo:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 0, uses_anonymous_args = 0
stmfd sp!, {r4, lr}
ldr ip, .L8
sub sp, sp, #8
ldr r4, .L8+4
ldr lr, .L8+8
str r0, [sp, #4]
str r0, [sp, #0]
mov r0, #0
fldd d5, [sp, #0]
.L2:
add r1, r0, ip
add r3, r0, r4
add r2, r0, lr
add r0, r0, #8
cmp r0, #1024
fldd d7, [r3, #0]
vmul.i32 d7, d5, d7 <--ここ
fldd d6, [r2, #0]
vadd.i32 d7, d7, d6 <--ここ
fstd d7, [r1, #0]
bne .L2
add sp, sp, #8
ldmfd sp!, {r4, pc}
.L9:
.align 2
.L8:
.word a
.word b
.word c
.size foo, .-foo
.comm a,1024,8
.comm b,1024,8
.comm c,1024,8
.ident "GCC: (CodeSourcery Sourcery G++ Lite 2007q3-51) 4.2.1"
.section .note.GNU-stack,"",%progbits


ちょっと速度計測するためにBeagleBoardUbuntuコンパイルして空演算を実行してみる。

$ cat neon.c
int a[256], b[256], c[256];
foo(int x) {int i; for (i = 0; i < 256; i++) { a[i] = x * b[i] + c[i]; } }

int main(void) {int i; for (i = 0; i < 1000000; i++) {foo(10);} return 0;}

$ gcc -o noneon neon.c
$ gcc -o noneon_o3 -O3 neon.c
$ gcc -o neon -O3 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize neon.c
$ time ./noneon
$ time ./noneon_o3
$ time ./neon

とか

オプションなし 13.516s
-O3のみ 4.727s
-O3 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize 3.383s

ふーん。
-O3だけだとNEON命令生成されないみたい。純粋に-O3同士で比べると0.3倍速い。
(volatileつけないと-O3で揮発しちゃうかもしれないんだけど)
今度ちゃんとしたプログラム書いて評価してみよ。


あと今回CodeSourcery2007q3使ったけど
公式みると2009q3でNEONのパフォーマンスが改善されたっぽい。
次は2009q3の評価も。
というかBeagleBoardの記事でよく2007q3使ってるのはなんでなんだろ?