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

インテル® DPC++/C++ コンパイラー

バージョン 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 の旧方式に従ってソースを作成されることをお勧めします。

タイトルとURLをコピーしました