ベクトル化レポート

ベクトル化レポートは、ストリーミング SIMD 拡張命令 2 (SSE2) およびストリーミング SIMD 拡張命令 3 (SSE3) のベクトル化を利用しているループと利用していないループについての情報を提供します。ベクトル化レポートは、IA-32 およびインテル(R) EM64T 対応システムで利用可能です。

-vec-report (Linux*) または /Qvec-report (Windows*) オプションは、異なるレベルの情報を含むベクトル化レポートを生成するようにコンパイラーに指示します。このオプションを使用して、レポートに設定する診断メッセージを制御できます。レポートをテキストファイルにリダイレクトする場合、以下のようなコマンドを使用します。

プラットフォーム

コマンド

Linux

icc -xW -vec-report3 matrix1.c > report.txt

Windows

icl /QxW /Qvec-report3 matrix1.c > report.txt

このオプションに関する詳細は、次のトピックを参照してください。

その他のベクトライザーのオプションに関する情報は、「並列処理の概要」を参照してください。

次に、ベクトル化レポートによって生成される結果の例を示します。

結果の例

multiply.c(10) : (col. 2) remark: loop was not vectorized: not inner loop.

multiply.c(11) : (col. 6) remark: loop was not vectorized: not inner loop.

multiply.c(12) : (col. 5) remark: vector dependence: assumed FLOW dependence between c line 13 and b line 13.

multiply.c(12) : (col. 5) remark: vector dependence: assumed FLOW dependence between c line 13 and a line 13.

multiply.c(12) : (col. 5) remark: vector dependence: assumed FLOW dependence between c line 13 and c line 13.

multiply.c(12) : (col. 5) remark: loop was not vectorized: existence of vector dependence.

ベクトル依存が存在するために、コンパイラーが "Loop was not vectorized" とレポートした場合、ループのベクトル依存解析を行う必要があります。

ベクトル依存が存在しないことがわかっている場合、上記のメッセージは、コンパイラーがループ中のポインターまたは配列が依存していると仮定していたか、ポインターまたは配列がエイリアスされていたことを示します。これらの場合、コンパイラーがベクトル化するように、メモリー一義化テクニックを使用します。

主要なベクトル依存は、FLOWANTI、および OUTPUT の 3 つあります。

ベクトル依存が有効かどうかを判断するには、「ループの独立性」を参照してください。コンパイラー・レポートは、何もないところでベクトル依存があると報告することがあります。これは、コンパイラーがメモリー・エイリアシングを仮定するためです。これらの場合に行うべき処理は、依存用のコードを検証することです。何もない場合、「メモリー・エイリアシング」セクションで説明されている手法を使用してコンパイラーに知らせます。

ベクトル化レポートは、さまざまな状況でベクトル依存を示します。以下のような状況で、非ユニットストライド、低いトリップカウント、複雑な添字式がベクトル依存としてレポートされることがあります。

非ユニットストライド

メモリーが非ユニットストライド方式でアクセスされたときに、ループがベクトル化できなかったことがレポートで示されることがあります。これは、ループで連続していないメモリーの場所がアクセスされていることを意味します。この場合、ループ交換で問題が解決できないか確認してください。解決できない場合、vector always プラグマによってベクトル化するように指定します。この際、状況が改善されたかを確認してください。

非ユニットストライド条件に関する詳細は、「ランタイム・パフォーマンスの理解」を参照してください。

その他のオプションの使用方法

ベクトル化レポートは、実行ファイルが生成される最後のコンパイルフェーズで生成されます。したがって、レポートを生成する場合に使用できないオプションの組み合わせがあります。次のオプションの組み合わせを使用した場合、コンパイラーは警告を表示してレポートを生成しません。

次のコマンド例は、ベクトル化レポートを生成できます。

プラットフォーム

コマンド例

Linux

次のコマンドは、ベクトル化レポートを生成します。

icpc -xK -vec_report3 file.cpp

icpc -xK -ipo -ipo_obj -vec_report3 file.cpp

icpc -c -xK -ipo -ipo_obj -vec_report3 file.cpp

次のコマンドは、ベクトル化レポートを生成しません。

icpc -c -xK -vec_report3 file.cpp

icpc -xK -ipo -vec_report3 file.cpp

icpc -c -xK -ipo -vec_report3 file.cpp

Windows

次のコマンドは、ベクトル化レポートを生成します。

icl /QxK /Qvec_report3 file.cpp

icl /QxK /Qipo /Qipo_obj /Qvec_report3 file.cpp

icl /c /QxK /Qipo /Qipo_obj /Qvec_report3 file.cpp

次のコマンドは、ベクトル化レポートを生成しません。

icl /c /QxK /Qvec_report3 file.cpp

icl /QxK /Qipo /Qvec_report3 file.cpp

icl /c /QxK /Qipo /Qvec_report3 file.cpp

レポート結果に基づくコードの変更

以下の条件でベクトル化できるようにするには、既存のコードを変更する必要があります。

例えば、同一の出力を行う 2 つの同等なアルゴリズムを考えます。"foo" はフロー依存のためにベクトル化されませんが、"bar" はベクトル化されます。

void foo(double *y)

{

  for(int i=1;i<10;i++) {  // a loop that puts sequential numbers into array y

    y[i] = y[i-1]+1;

  }

}

void bar(double *y)

{

  for(int i=1;i<10;i++) { // a loop that puts sequential numbers into array y

    y[i] = y[0]+i;

  }

}

サポートされていないループ構造はベクトル化できません。サポートされていないループ構造の例は、複雑な計算が必要なループ・インデックス変数です。構造を変更して、ループ制限への関数呼び出しおよびループ制限に対するその他の過度な計算を削除します。

int function(int n)

{

  return (n*n-1);

}

void unsupported_loop_structure(double *y, int n)

{

  for (int i=0; i<function(n); i++) {

    *y = *y * 2.0;

  }

}

非ユニット・ストライド・アクセスは、ベクトル化レポートで vectorization possible but seems inefficient のように示されます。ユニットストライド方式でデータにアクセスするようにループを再構成 (例えば、ループ交換を適用) するか、またはプラグマ vector always を使用します。

ループの中で混在データ型を使用するとベクトル化できません。混在データ型の場合、ベクトル化レポートで loop was not vectorized: condition too complex のように示されます。

次に、ループ内に混在データ型が使用されているためにベクトル化できないループの例を示します。例えば、withinborderint ですが、ループの他のデータ型はすべて double として定義されています。withinborder のデータ型を double に変更することで、このループをベクトル化できます。

int howmany_close(double *x, double *y)

{

  int withinborder=0;

  double dist;

  for(int i=0;i<100;i++) {

    dist=sqrtf(x[i]*x[i] + y[i]*y[i]);

    if (dist<5) withinborder++;

  }

  return 0;

}