自動ベクトル化の使用

自動ベクトライザーはインテル® コンパイラーのコンポーネントです。コンパイラーは、インテル® ストリーミング SIMD 拡張命令 (インテル® SSE、SSE2、SSE3 および SSE4 ベクトル化コンパイラー命令およびメディア・アクセラレーター命令)、ストリーミング SIMD 拡張命令 3 補足命令 (SSSE3)、インテル® Advanced Vector Extension (インテル® AVX) 命令を自動的に使用します。ベクトライザーは、並列に実行できるプログラム内の演算を検出し、データ型により、2、4、8、または 16 までの要素を並列で処理する 1 つの SIMD 命令に変換します。

ベクトル化とは一体何でしょうか? スカラー実装 (一度にオペランドの 1 ぺアに対する演算を行う) からベクトル処理 (1 つの命令がベクトル (一連の隣接した値) を参照できる) にアルゴリズムを変換するプロセスをベクトル化と呼びます。SIMD 命令は複数のデータ要素を 1 つの命令で演算し、128 ビット浮動小数点レジスターを使用します。

自動ベクトル化は、インテル® コンパイラーがループをアンロールするためにパックド SIMD 命令を生成する際に行われます。パックド命令は一度に複数のデータ要素で演算するため、ループがより効率良く実行されます。このプロセスは、開発者が特別な処理をすることなく、コンパイラーが適したループを独自に識別し最適化するため、自動ベクトル化と呼ばれています。場合によっては、コードに特定のキーワードや宣言子を追加して、自動ベクトル化が行われるようにすることができます。

自動ベクトル化は、IA-32 アーキテクチャーとインテル® 64 アーキテクチャーでサポートされています。

-vec (Linux* および Mac OS* X) または /Qvec (Windows*) オプションを使用すると、インテル製マイクロプロセッサーおよび互換マイクロプロセッサーにおいて、デフォルトの最適化レベルでベクトル化が有効になります。ベクトル化により呼び出されるライブラリー・ルーチンは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーにおいてより優れたパフォーマンスが得られる可能性があります。また、ベクトル化は、/arch/Qx (Windows*) または -m-x (Linux* および Mac OS* X) などの特定のオプションによる影響を受けます。

ベクトル化によるスピードアップ

ベクトル化によるスピードアップはどのようにもたらされるでしょうか? 次に示すコード例について考えてみます。abc は整数配列です。

for (i=0;i<=MAX;i++)
   c[i]=a[i]+b[i];

ベクトル化が有効ではない場合 (つまり、/O1 または /Qvec- オプションを使用してコンパイルする場合)、コンパイラーはそれぞれの反復で各 SIMD レジスターに追加で 3 つの整数を保持できる空間があったとしても、それらを活用せずに (未使用のまま) コードを生成します。ベクトル化が有効な場合 (/O2 以上のオプションを使用してコンパイルする場合)、コンパイラーは SIMD レジスターの未使用の空間を活用して、1 つの命令で 4 つの加算を実行します。デフォルトの最適化オプション (-O2) またはそれ以上でコンパイルすると、コンパイラーは常にベクトル化の機会を探します。

Tip iconヒント

ベクトル化されたコードとベクトル化されていないコードを比較するために、/Qvec- (Windows*) または -no-vec (Linux* および Mac OS* X) オプションを使用してベクトル化を無効にしたり、/O2 または -O2 オプションで有効にしてみてください。

ループがベクトル化されたがどうかを確認するには、/Qopt-report:1 /Qopt-report-phase hpo (Windows*) または -opt-report1 -opt-report-phase hpo (Linux* および Mac OS* X) オプションを使用して、ベクトル化レポートを生成します。次のように、ベクトル化された各ループに対して 1 行のメッセージが生成されます。

> icl /Qvec-report1 MultArray.c
MultArray.c(92): (列 5) リマーク: ループがベクトル化されました。

ソースの行番号 (上記の例では 92) はループの始めか終わりを指します。

パフォーマンスの向上はどの程度のものでしょうか? パフォーマンスの向上を評価するには、以下の例 example1 を実行してみてください。

  1. インテル® コンパイラーのコマンドウィンドウを開きます。[スタート] > [すべてのプログラム] > [Intel(R) Software Development Tools (インテル(R) ソフトウェア開発ツール)] > [Intel(R) C++ Compiler Professional (インテル(R) C++ コンパイラー・プロフェッショナル)] から [C++ Build Environment for applications running on <architecture-name> ( <architecture-name> 対応アプリケーション用 C++ ビルド環境)] を選択します。
  2. \example1 ディレクトリーに移動します。この小さなプログラムは、次のループを使用してベクトルに行列を掛けます。
    for (j = 0;j < size2; j++) {
          b[i] += a[i][j] * x[j];
    }
  3. 最初は自動ベクトル化を無効にして、プログラムをビルドし実行します。プログラムの実行時間に注目してください。Windows* OS では次を入力します。
    icl /O2 /Qvec- MultArray.c /FeNoVectMult
    NoVectMult
  4. 次に自動ベクトル化を有効にして、プログラムをビルドし実行します。プログラムの実行時間に注目してください。Windows* OS では次を入力します。
    icl /O2 /Qvec-report1 MultArray.c /FeVectMult
    VectMult

2 つの実行時間を比較すると、ベクトル化されたバージョンのほうが速いことがわかるでしょう。ベクトル化されていないバージョンの実行時間は、/O1 オプションまたは -O1 オプションでコンパイルした場合より多少早いだけです。

ベクトル化の妨げ

次に示す状況が必ずベクトル化を妨げるわけではありませんが、頻繁にベクトル化を阻んだり、コンパイラーがベクトル化の利点がないと判断する原因になります。

インテル® コンパイラーのベクトル化を支援

場合によっては、コンパイラーがループのベクトル化を判断するための情報が不足していることがあります。コンパイラーに追加情報を提供する方法はいくつかあります。


このヘルプトピックについてのフィードバックを送信

© 1996-2011 Intel Corporation. 無断での引用、転載を禁じます。