OpenMP 4.0 を使用してプログラムで SIMD を有効にする

同カテゴリーの次の記事

インテル® コンパイラー V15 におけるレポート機能の変更点

この記事は、インテル® デベロッパー・ゾーンに掲載されている「Enabling SIMD in program using OpenMP 4.0」の日本語参考訳です。


OpenMP 4.0 仕様で導入された主要機能の 1 つは、プログラム中でプラグマを使って明示的にベクトル化/SIMD を有効にすることです。以下は、OpenMP 4.0 が提供する明示的なベクトル化指示の例です:

1. #pragma omp simd

#pragma omp simd を使用するベクトル化は、コンパイラーにループをベクトル化するように指示します。コードのベクトル化に必要なソースコードの変更は、最小限に抑えるように設計されています。”omp simd” プラグマを使用すると、「#pragma vector always」や「#pragma ivdep」などのベクトル化のヒントを利用しても、コンパイラーが自動ベクトル化しないループをベクトル化できます。

char foo(char *A, int n){
int i;
char x = 0;
#ifdef SIMD
#pragma omp simd reduction(+:x) 
#endif
#ifdef IVDEP
#pragma ivdep
#endif
for (i=0; i<n; i++){
x = x + A[i];
}
return x;
}

>icl /c /Qvec-report2 simd.cpp -openmp
simd.cpp
simd.cpp(12) (列 3) リマーク: ループはベクトル化されませんでした: ベクトル依存関係が存在しています。
>icl /c /Qvec-report2 simd.cpp /DIVDEP -openmp
simd.cpp
simd.cpp(12) (列 3) リマーク: ループはベクトル化されませんでした: ベクトル依存関係が存在しています。
>icl /c /Qvec-report2 simd.cpp /DSIMD -openmp
simd.cpp
simd.cpp(12) (列 3) リマーク:OpenMP SIMD LOOP がベクトル化されました。

プラグマには、いくつかの句を指定することができますが、それらは常に関数本体の動作に関して関連する適切な句を使用することを推奨します。”omp simd” プラグマの詳細に関しては、http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf の 2.8.1 節をご覧ください。

2. #pragma omp declare simd

C/C++ 言語における関数は、伝統的にスカラー引数を受け取って、スカラー値を返します。この動作は、関数呼び出しを伴うループをベクトル化する際にボトルネックとなります。ループ本体をベクトル化する過程で、それぞれスカラーオペランドを使用せずベクトルオペランドを使用するようにします。この状況で、ベクトル引数を受け入れず、ベクトル値を返さない関数呼び出しに遭遇すると、ループ本体をベクトル化する上で深刻なボトルネックを引き起こします。このような状況で、OpenMP 4.0 の新機能は、スカラー関数のベクトル処理を行うバリエーションを生成するようにコンパイラーに指示できます。次のコードは、プラグマの使い方を示す例です:

	#pragma omp declare simd
int vfun_add_one(int x)
{
return x+1;
}

>icl /c /Qvec-report2 elementalfunc.cpp -openmp
elementalfunc.cpp
elementalfunc.cpp(3) (列 1) リマーク:FUNCTION がベクトル化されました。

プラグマには、いくつかの句を指定することができますが、それらは常に関数本体の動作に関して、関連する適切な句を使用することを推奨します。”omp simd” プラグマの詳細に関しては、http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf の 2.8.2 節をご覧ください。

3. スレッド化と SIMD で同じ “for” ループをターゲットにする:

OpenMP 4.0 では、SIMD モードを実行する複数の OpenMP スレッドによって “for” ループを実行するようにコンパイラーに指示できます。例:

	char foo(char *A, int n){
int i;
char x = 0;
#pragma omp parallel for simd
for(i = 0; i < n; i++)
x = x + A[i];
return 0;
}

$ icc test.c -c -vec-report2 -c -openmp-report2 -openmp
test.c(4): (列 1) リマーク: OpenMP 定義ループが並列化されました。
test.c(5): (列 1) リマーク: OpenMP SIMD LOOP がベクトル化されました。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事

  • OpenMP* でベクトル化された並列ループを簡単に作成するOpenMP* でベクトル化された並列ループを簡単に作成する この記事は、インテル® デベロッパー・ゾーンに掲載されている「How to Create Vectorized, Multicore Loops in OpenMP with Ease」の日本語参考訳です。 OpenMP* のプラグマ宣言子を使用すると、1 […]
  • ベクトル異形関数でのプロセッサー ID 指定ベクトル異形関数でのプロセッサー ID 指定 インテル® C/C++ および Fortran コンパイラーのバージョン 16.0 以降では、プログラマーがスカラー関数に対応するベクトル関数を明示的に記述することを可能にする、ベクトル異形関数 (Vector Variant Function) をサポートしています。 Windows* および Linux* […]
  • OpenMP* 関連のヒントOpenMP* 関連のヒント この記事は、インテル® ソフトウェア・サイトに掲載されている「OpenMP Related Tips」の日本語参考訳です。 OpenMP* ループの一重化 各スレッドで処理される作業の粒度を減らすことで利用可能なスレッド全体で分割される反復の総数を増やすには、OpenMP* collapse […]
  • ループのベクトル化によるプログラムの最適化ループのベクトル化によるプログラムの最適化 この記事は、インテル® デベロッパー・ゾーンに掲載されている「Program Optimization through Loop Vectorization」の日本語参考訳です。 はじめに この記事では、有限差分ステンシル計算を例に、インテル® メニー・インテグレーテッド・コア (インテル® MIC) […]
  • OpenMP* 4.0 API C/C++ シンタックス・クイック・リファレンス・カードOpenMP* 4.0 API C/C++ シンタックス・クイック・リファレンス・カード OpenMP* 4.0 API C/C++ Syntax Quick Reference Card (英語) の日本語版が公開されました。 日本語版はこちらから入手できます。 このクイック・リファレンス・カードを『インテル® C++ コンパイラー 15.0 ユーザー・リファレンス・ガイド』と同じフォルダー内 (デフォルトでは \ […]