インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

自動ベクトル化の使用

自動ベクトル化は、IA-32 アーキテクチャーとインテル® 64 アーキテクチャーでサポートされています。ここでは、自動ベクトルの設定に役立つ情報を提供します。

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

ベクトル化によるスピードアップはどのようにもたらされるでしょうか? 次に示すコード例について考えてみます。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* および macOS*)、[Q]x などの特定のオプションによる影響を受けます。

ヒント

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

ループがベクトル化されたがどうかを確認するには、Qopt-report:1 Qopt-report-phase:vec (Windows*) または qopt-report=1 qopt-report-phase=vec (Linux* および macOS*) オプションを使用して、最適化化レポートを生成します。これらのオプションは、*.optrpt ファイルに最適化メッセージを含む異なるレポートを生成します。Visual Studio* では、ソースファイルにレポートメッセージのアノテーションが付けられます。生成された .optrpt ファイルをテキストエディターで開いて確認することもできます。次のように、ベクトル化されたループごとにメッセージが出力されます。

ベクトル化レポートの例

> 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 を使用してループがベクトル化されたかどうかの情報を得るには、[プロジェクト] > [プロパティ] > [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* および macOS*: <installdir>/bin ディレクトリーにある compilervars.sh または compilervars.csh などの環境スクリプトを、アーキテクチャーに応じた属性を使用して source コマンドで実行します。

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

    ベクトル行列乗算の例

    for (j = 0;j < size2; j++) { b[i] += a[i][j] * x[j]; }
  3. 最初は自動ベクトル化を無効にして、プログラムをビルドし実行します。デフォルトの O2 最適化は、ベクトル化を有効にするため、別のオプションにより無効にする必要があります。プログラムの実行時間に注目してください。

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

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

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

    // (Linux* および macOS*)
    vicc -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++ コンパイラーがループのベクトル化を判断するための情報が不足していることがあります。コンパイラーに追加情報を提供する方法はいくつかあります。

関連情報