V15 と V16 のコンパイラーのオフロード時のコンパイラーの振る舞いの違い

同カテゴリーの次の記事

インテル® SSE およびインテル® AVX 世代 (SSE2、SSE3、SSSE3、ATOM_SSSE3、SSE4.1、SSE4.2、ATOM_SSE4.2、AVX、AVX2、AVX-512) 向けのインテル® コンパイラー・オプションとプロセッサー固有の最適化

バージョン 15 と 16 のコンパイラーのユーザーズガイドには、Offload を使用する場合の制限に、

変数をターゲットで使用できるようにするには、オフロードコード内から呼び出される関数で参照されるグローバル変数が、一致するターゲット属性で宣言されている必要があります。オフロードコードはホスト CPU のグローバル変数にアクセスできません。これはコンパイラーによる制約です。
 
デフォルトでは、ポインター変数は対応する型の単一要素を指すと仮定されます。オフロードコードはポインターを逆参照して単一要素にアクセスできます。ポインターが指すデータ要素はターゲットメモリーおよび調整されたポインター値に自動的にコピーされます。element-count-expr 式と in / out / inout パラメーターを使用して、可変長データをコピーできます。
というのがあります。

#include <omp.h>
#include <time.h>

static long num_steps = 1000000000;
double step;
double start, end;

int main (){    
int i; 	  
double pi, x, sum = 0.0;

step = 1.0/(double) num_steps;
start = clock();

#pragma offload target(mic) in(x, num_steps, step) out(sum) 
#pragma omp parallel for simd reduction(+:sum) private(x)
     for (i=0;i< num_steps; i++){
	x = (i+0.5) * step;
	sum = sum + 4.0/(1.0+x*x);
     }
   pi = step * sum;
end = clock();
printf("Pi = %f Time = %f\n", pi, (double)((end-start)/CLOCKS_PER_SEC));
}

上記のソースを、V15 のコンパイラーでコンパイルすると、以下のエラーになります。

pi1_err.c(18): エラー: オフロード領域で使用される 変数 "num_steps" には互換性のある "target" 属性がなければなりません。
  #pragma offload target(mic) optional in(x, num_steps, step) out(sum)
                                             ^
pi1_err.c(18): エラー: オフロード領域で使用される 変数 "step" には互換性のある "target" 属性がなければなりません。
  #pragma offload target(mic) optional in(x, num_steps, step) out(sum)
                                                        ^

しかし、V16 (16.0.0.079) でコンパイルすると、コンパイルおよび実行できてしまいます。V16 のマニュアル表記もほぼ同じですが、これはマニュアルのエラーのようです。

インテル® C/C++ コンパイラー V16 は、OpenMP* 4.1 のサポートに向けてオフロード構文のデータスコープにけるグローバルデータの扱いが変わりました。これに伴い、オフロード向けのインテル® コンパイラー言語拡張の振る舞いも変更されたようです。オフロードプラグマの構文内で参照されるグローバルデータは、ターゲット属性と一致する宣言を行う必要がなく、関連する変数の値はデフォルトでコプロセッサー環境に転送 (送受信) されます。

V15 向けには正式には次のように記述する必要があります。V16 は以下でも OK;

#include <omp.h>
#include <time.h>

__declspec(target(mic)) static long num_steps = 1000000000;
__declspec(target(mic)) double step;
もしくは
#pragma offload_attribute(push, target(mic))
static long num_steps = 1000000000;
double step;
#pragma offload_attribute(pop)
double start, end;

int main ()
{    
int i; 	  
double pi, x, sum = 0.0;

step = 1.0/(double) num_steps;

start = clock();

#pragma offload target(mic) in(x, num_steps, step) out(sum)
#pragma omp parallel for simd reduction(+:sum) private(x)
     for (i=0;i< num_steps; i++){
	x = (i+0.5)*step;
	sum = sum + 4.0/(1.0+x*x);
     }
   pi = step * sum;
end = clock();
printf("Pi = %f Time = %f\n", pi, (double)((end-start)/CLOCKS_PER_SEC));
}

V16 のコンパイラーを使用して開発したオフロード構文を含むソースを、V15 のコンパイラーでコンパイルした場合、前述のようなエラーが発生する可能性が非常に高いと思われます。複数のバージョンのコンパイラーを使用して、オフロードを行うアプリケーションを開発する場合、V15 の旧方式に従ってソースを作成されることをお勧めします。

関連記事

  • インテル® コンパイラー V15 におけるレポート機能の変更点インテル® コンパイラー V15 におけるレポート機能の変更点 インテル® コンパイラーの主要機能の一つに、コンパイル時にソースコードを解析して、ベクトル化、並列化、OpenMP […]
  • HPL 向けアプリケーション・ノートHPL 向けアプリケーション・ノート この記事は、インテル® ソフトウェア・ネットワークに掲載されている「HPL application note」の日本語参考訳です。 ステップ 1 - 概要 このガイドは、現在 HPL を使用しているユーザーが、より優れたベンチマーク結果を得られるように、インテル® マス・カーネル・ライブラリー (インテル® MKL) の […]
  • インテル® System Studio を使用する理由インテル® System Studio を使用する理由 この記事は、インテル® デベロッパー・ゾーンに掲載されている「Should I use Intel® System Studio?」の日本語参考訳です。 はじめに インテル® System Studio は、インテル® […]
  • ベクトル異形関数でのプロセッサー ID 指定ベクトル異形関数でのプロセッサー ID 指定 インテル® C/C++ および Fortran コンパイラーのバージョン 16.0 以降では、プログラマーがスカラー関数に対応するベクトル関数を明示的に記述することを可能にする、ベクトル異形関数 (Vector Variant Function) をサポートしています。 Windows* および Linux* […]
  • 明示的なベクトル・プログラミング – 最も一般的な手法明示的なベクトル・プログラミング – 最も一般的な手法 この記事は、インテル® デベロッパー・ゾーンに掲載されている「Explicit Vector Programming – Best Known Methods」の日本語参考訳です。 明示的なベクトル・プログラミング – […]