インテル® C++ コンパイラー 15.0 ユーザー・リファレンス・ガイド

自動ベクトル化の使用

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

自動ベクトル化はインテル® コンパイラーのコンポーネントです。コンパイラーは、インテル® ストリーミング SIMD 拡張命令 (インテル® SSE、インテル® SSE2、インテル® SSE3、およびインテル® SSE4 ベクトル化コンパイラー命令およびメディア・アクセラレーター命令)、インテル® ストリーミング SIMD 拡張命令 3 補足命令 (インテル® SSSE3)、インテル® アドバンスト・ベクトル・エクステンション (インテル® AVX) 命令を自動的に使用します。

ベクトル化機能は、並列に実行できるプログラム内の演算を検出し、データ型によって最大 16 までの要素を並列に処理する 1 つの SIMD 命令に変換します。

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

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

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

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

コード例

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

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

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

ヒント

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

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

ベクトル化レポートの例

> icl /Qopt-report:1 /Qopt-report-phase:vec  Multiply.c 
Multiply.c(92): (列 5) リマーク: ループがベクトル化されました。

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

適用されたループ変換と最適化の種類を確認するには、[Q]opt-report-phase オプションだけを指定するか、[Q]opt-report オプションと一緒に指定します。

Visual Studio* IDE を使用してループがベクトル化されたかどうかの情報を得るには、[Project (プロジェクト)] > [Properties (プロパティー)] > [C/C++] > [Diagnostics (診断)] > [Optimization Diagnostic Level (最適化診断レベル)][Level 1 (/Qopt-report:1) (レベル 1 (/Qopt-report:1))] を、[Optimization Diagnostic Phase (最適化診断フェーズ)][Loop Nest Optimization (/Qopt-report-phase:loop) (ループの入れ子構造の最適化 (/Qopt-report-phase:loop))] を選択します。 ベクトル化されなかった各ループに対する診断メッセージと、ベクトル化されなかった理由の説明を取得するには、/Qopt-report-phase:vec を選択します。

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

  1. インテル® コンパイラーのコマンドウィンドウを開きます。

    • Windows*: [スタート] メニューのインテル製品項目にある [Compiler and Performance Libraries (コンパイラーおよびパフォーマンス・ライブラリー)] > [Command Prompt with Intel Compiler (インテル® コンパイラー用コマンドプロンプト)] からアイコンを選択します。

    • Linux* および OS X*:<installdir>/bin ディレクトリーにある compilervars.sh または compilervars.csh などの環境スクリプトを、アーキテクチャーに応じた属性を使用して source コマンドで実行します。

  2. <install-dir>\Samples\<locale>\C++\ ディレクトリーに移動します。 サンプル・プロジェクト vec_samples.zip を開きます。 この小さなプログラム example1 は、次のループを使用してベクトルに行列を掛けます。

  3. ベクトル行列乗算の例

    for (j = 0;j < size2; j++) { b[i] += a[i][j] * x[j]; }

    最初は自動ベクトル化を無効にして、プログラムをビルドし実行します。プログラムの実行時間に注目してください。

    自動ベクトル化なしのアプリケーションのビルドと実行の例

    // (Linux*)
    icc -O2 -no-vec  Multiply.c -o NoVectMult 
    ./NoVectMult
    // (OS X*)
    icl -O2 -no-vec  Multiply.c -o NoVectMult 
    ./NoVectMult
    // (Windows*)
    icl /O2 /Qvec- Multiply.c /FeNoVectMult 
    NoVectMult
  4. 次に自動ベクトル化を有効にして、プログラムをビルドし実行します。プログラムの実行時間に注目してください。

    自動ベクトル化ありのアプリケーションのビルドと実行の例

    // (Linux*)
    icc -O2 -qopt-report=1 -qopt-report-phase=vec Multiply.c -o VectMult 
    ./VectMult
    // (OS X*)
    icc -O2 -qopt-report=1 -qopt-report-phase=vec Multiply.c -o VectMult 
    ./VectMult
    // (Windows*)
    icl /O2 /Qopt-report:1 /Qopt-report-phase:vec Multiply.c /FeVectMult 
    VectMult

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

ベクトル化を妨げる要因

次に示す状況が必ずしもベクトル化を妨げるわけではありませんが、コンパイラーがベクトル化のメリットがないと判断する原因になります。

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

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

関連情報


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