SIMDを使おう

SIMDとは?


SIMD(single instruction multiple data)とは1回の命令で複数のデータを処理することを言います。
ARM Cortex-M4コアにはCortex-M0/1/3の命令に加えてDSP(デジタル信号処理)を意識したSIMDがあり、これを使用することで処理を高速化できます。

cortex-m_instruction_set.jpg

Cortex-M4 SIMD一覧


CMSISのCOREドキュメントで閲覧できます。

SIMDはCMSISヘッダファイルから簡単呼び出し


ARM社が提供しているCMSISソフトウェアインターフェースを使えば簡単にSIMDが呼び出せます。
core_cm4_simd.hというヘッダファイルにSIMDをインラインアセンブラで埋め込んだ関数が定義されています。

CMSISのダウンロード先

SIMDの効果


SIMDを使うことでどれくらい処理が高速化されるのか見てみましょう。
例えばsigned char型の2つの配列array0とarray1があり、各要素ごとに加算して結果をarray_outに代入するという処理を行ってみます。

普通の加算


for(i = 0;i < sizeof(array0) / sizeof(array0[0]);i++){
   array_out[i] = array0[i] + array1[i];
}

SADD8命令を使った加算


uint32_t *p0, *p1, *p_out;
p0 = (uint32_t*)array0; 
p1 = (uint32_t*)array1;
p_out = (uint32_t*)array_out;

for(i = 0;i < sizeof(array0) / sizeof(array0[0]) / 4;i++){
   *p_out++ = __SADD8(*p0++, *p1++);
}

実行結果


STM32F4 CPUクロック周波数168MHzにおいて配列の要素数を1024として上のコードをそれぞれ実行して計測した結果です。

  時間 比率
普通の加算 67μs 1
SADD8を使った加算 17μs 0.254

上の結果からSADD8を使った加算が普通の加算にくらべて4倍の速さで処理できたことが分かります。
これは普通の加算の場合は1個ずつ配列の要素を加算するのに対してSADD8命令を使った場合はsigned charを4個並列で加算しているためです。
ですので計算量も普通の加算に比べて1/4で済みます。

add.jpg

sadd8.jpg


サウンドプログラミングでのSIMDの具体的な使用例


符号付き16bit L・Rチャネルを32bitのステレオブロックにパックする


stereo_out = __PKHBT(left_out, right_out, 16);

pkhbt.003.jpg


ステレオブロックのL・R両チャネルのデータを1/2にする


stereo_out = __SHADD16(0, stereo_in);

shift.005.jpg


ステレオブロックの左右チャネル入れ替え(Cortex-M3/M4共通)


stereo_in = __REV(stereo_in);
stereo_out = __REV16(stereo_in);

swap.005.jpg



float型の音声信号データを符号付き16bitに変換し-32768以下32767以上で飽和させる


left_out = __SSAT((int32_t)(Sleft_out * 32768.0f), 16);
right_out = __SSAT((int32_t)(Sright_out * 32768.0f), 16);

  • 最終更新:2013-04-30 16:48:53

このWIKIを編集するにはパスワード入力が必要です

認証パスワード