診断 15344: ループはベクトル化されませんでした: ベクトル依存関係がベクトル化を妨げています。

同カテゴリーの次の記事

診断 15378: ループはベクトル化されませんでした: /Qfreestanding オプションが整数除算/剰余のベクトル化を妨げています。

この記事は、インテル® デベロッパー・ゾーンに掲載されている「Diagnostic 15344: loop was not vectorized: vector dependence prevents vectorizationxxxx」の日本語参考訳です。


このベクトル診断メッセージは、インテル® C++ コンパイラー 15.0 以降で生成されます。

原因:

この診断メッセージは、コンパイラーがループ反復間に (実際のまたは潜在的な) ベクトル依存関係を検出した際に出力されます。デフォルトのレベル 2 レポート (/Qopt-report:2) では、最初の依存関係情報のみが出力されます。ベクトル依存関係の詳細情報は、/Qopt-report:5 (Windows*) または -qopt-report=5 (Linux*) で取得できます。

例:

void foo(float *a, float *b, float *c, float *d, float *e){
for(int i = 0 ; i < 256; i++)
        a[i] = b[i] + c[i] + d[i] + e[i];
}

$ icl 15344.c /c /Qstd=c99 /Qopt-report:2 /Qopt-report-phase:vec

以下の診断メッセージは、インテル® C++ コンパイラー for Windows* 19.1.0.166 (ビルド 20191121) で生成しました。

最適化レポート開始: foo(float *, float *, float *, float *, float *)

    レポート: ベクトルの最適化 [vec]

ループの開始 D:\15344.c(2,1)
   リマーク #15344: ループ はベクトル化されませんでした: ベクトル依存関係がベクトル化を妨げています。最初の依存関係を以下に示します。詳細については、レベル 5 のレポートを使用してください。
リマーク #15346: ベクトル依存関係: FLOW の依存関係が a[i] (3:10) と b[i] (3:10) の間に仮定されました。
ループの終了

この例では、コンパイラーは a が他の引数とエイリアスであると想定します (例えば、ab が指すデータがオーバーラップする可能性がある)。この場合、a への書き込みより入力引数の 1 つが使用される前に上書きされる可能性があります。これにより誤った結果が生成される可能性があるため、コンパイラーはベクトル化しないことを選択します。

解決方法:

a が他のポインターとエイリアスでないことが判明している場合、いくつかの方法でそれをコンパイラーに知らせることができます。

  • /Qalias-args- (Windows*) または -farguments-noalias (Linux*) オプションでコンパイルします (関数の引数が互いにオーバーラップしないことを明示します)。
  • restrict” キーワードを追加して、a が指すデータが他のポインターからアクセスされないことを明示します (restrict は書き込まれるポインターに対して指定します)。関数の最初の行は次のようになります。

    void foo(float *restrict a, float *b, float *c, float *d, float *e) {

  • for ループの直前に #pragma ivdep を挿入し、潜在的な依存関係を無視しても安全であることをコンパイラーに伝えます (実際の依存関係は無視されません)。
  • for ループの直前に #pragma omp simd を挿入し、/Qopenmp-simd (Windows*) または -qopenmp-simd (Linux*) を指定してコンパイルします。これはコンパイラーに for ループのベクトル化を強制します。この場合、コンパイラーは依存関係解析を行わないため、複雑なループでは simd プラグマの追加の節を使用して、プライベート変数やリダクション変数などの情報をコンパイラーに使えることが重要です。

上記のいずれかの方法でループはベクトル化されます。使用するのは 1 つのみです。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事