インテル® Fortran コンパイラー 14.0 ユーザー・リファレンス・ガイド

自動ベクトル化の使用

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

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

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

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

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

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

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

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

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

ヒント

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

ループがベクトル化されたがどうかを確認するには、[Q]vec-report[:]1 または [Q]opt-report-phase hpo オプションを使用して、ベクトル化レポートを生成します。 次のように、ベクトル化された各ループに対して 1 行のメッセージが生成されます。

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

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

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

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

  1. インテル® コンパイラーのコマンドウィンドウを開きます。
    • Windows*: [スタート] > [すべてのプログラム] > [Intel Parallel Studio XE 2013 (インテル® Parallel Studio XE 2013)] > [Command Prompt (コマンドプロンプト)] > [Parallel Studio XE with Intel Compiler XE 2013 (インテル® コンパイラー XE)] メニュー項目の [IA-32 Visual Studio 2008 モード] など、使用するコマンドライン・モードを選択します。

    • Linux*: コンパイラーの /bin/intel64 ディレクトリーにある iccvars_intel64.sh または /bin/ia32 ディレクトリーにある iccvars_ia32.sh などの環境スクリプトを 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* および OS*X)
    icc -O2 -no-vec  Multiply.c -o NoVectMult 
    ./NoVectMult
    // (Windows*)
    icl /O2 /Qvec- Multiply.c /FeNoVectMult 
    NoVectMult
  4. 次に自動ベクトル化を有効にして、プログラムをビルドし実行します。プログラムの実行時間に注目してください。
    // (Linux* および OS*X)
    icc -O2 -vec-report1 Multiply.c -o VectMult 
    ./VectMult
    // (Windows*)
    icl /O2 /Qvec-report1 Multiply.c /FeVectMult 
    VectMult

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

ベクトル化を妨げる要因

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

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

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


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