Nanashi-soft○プログラマ専用○Linux ARM○
◇Linux ARM -ARMの NEON (SIMD)を操る(3-
実際にプログラミングを行ってみます
例えば,1から100を足してみる
もちろん,結果は 5050になる
普通に書くと,こんな感じになるでしょう
int ret=0;
int i;
for(i=1; i <= 100; i++){
ret += i;
}
printf("%d\n", ret);
これを SIMDで書くと,こんな感じです
○ソース「testsimd.c」
#include <stdio.h>
#include "arm_neon.h" //NEONを使うためのヘッダーはどこかから拾ってくる
int main(int args,char *argp[]){
int ret;
int32x4_t ret_work={0, 0, 0, 0};
volatile int *ret_workp=(int*)&ret_work;
//4つのベクタ変数それぞれに1つずつ割り当てて,4つに分割して計算する
int i;
for(i=1; i <= 100; i += 4){
int32x4_t i_work={i, i+1, i+2,
i+3};
//ret_work=ret_work+i_workで4つ一度に足す
ret_work=vaddq_s32(ret_work,
i_work);
}
//最後に分割計算した結果を足す
ret=ret_workp[0];
ret += ret_workp[1];
ret += ret_workp[2];
ret += ret_workp[3];
printf("%d\n", ret);
}
○コンパイル方法
gcc -mfloat-abi=softfp -mfpu=neon -o testsimd testsimd.c
この2つのオプションを付けて行います
-mfpu=neonは文字通り NEONを使うオプションでしょう
-mfloat-abi=softfpも必須な理由がよくわかりません
浮動小数点エミュレーションの-msoft-floatオプションとの互換性を保つ為のものらしいのですが……SIMDってどう考えてもハード実装なので
関係無いし
とりあえず付けとけ,ということで(*'-')
(たぶん説明見つけても意味が理解できないだろうし) ←
※ベクタ変数のポインタ定義をvolatile(最適化の禁止)を書くのは,宣言時に定数で代入しているせいか,-O2を付けると時々コンパイラが誤動作
するからです
今回使ったロジックは,4つに分割して足していき,
1つ目:1,5,9...
2つ目:2,6,10...
3つ目:3,7,11...
4つ目:4,8,12...
最後に,この4つの計算結果を1つにまとめる
というものです
こうすることで,ループ回数と演算回数が1/4に減ります
ただし,演算前後にベクタ変数に対する事前・事後操作のコストがある為,必ずしも高速化するとは限りません
(たぶんこの処理の場合普通に書いた方が速いです) ←
これであなたもシムドマスタ('-'*)
○TOP○プログラマ専用○Linux ARM○