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 &lt;stdio.h&gt;
#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