私はGPUにコードを持ってきています。このコードにはプライベート配列を使用するカーネルがあります。これは、配列がカーネルループ内で宣言されていることを意味します。OpenACC:すべてのGPUスレッド用にプライベートアレイを持っています
OpenACCにコードを移植すると、私はバグの多い結果になる。私にとって、 は、配列がGPUベクトルスレッド間で共有されているように見えます。これは、いくつかの競合状態を引き起こします。
これは私の元のコードのように外部呼び出しで構成しました。
がheader.h:
#define N 100000
#define K 16
#pragma acc routine
void assign_i_to_privj(int * priv, int j, int i);
#pragma acc routinetnumpy
void add_privi_to_sum(int * priv, int i, int *sum);
のmain.c:
#include "header.h"
int main(void){
int A[N];
#pragma acc data copy(A)
{
#pragma acc parallel loop
for(int i=0; i<N;i++){
int priv[K];
int sum=0;
int j=0;
while(1){
if(j>=K) break;
assign_i_to_privj(priv, j, i);
j++;
}
j=0;
while(1){
if(j>=K) break;
add_privi_to_sum(priv, j, &sum);
j++;
}
sum/=K; // now sum == i;
A[i]=sum;
}
}
//now A[i] == i
for(int i=0; i<123; i++) printf("A[%d]=%d ",i, A[i]);
printf("\n");
return 0;
}
f.c:
#include "header.h"
void assign_i_to_privj(int *priv, int j, int i){
priv[j]=i;
}
void add_privi_to_sum(int *priv, int j, int *sum){
(*sum)+=priv[j];
}
私はExport PGI=/opt/pgi/17.5.0
を返しcc -v
とコンパイラのバージョンを確認することができます。
cc -g -lnvToolsExt -O2 -acc -ta=tesla:cc60 -c11 -mp -Minfo -Mlarge_arrays -c main.c &&
cc -g -lnvToolsExt -O2 -acc -ta=tesla:cc60 -c11 -mp -Minfo -Mlarge_arrays -c f.c &&
cc -g -lnvToolsExt -O2 -acc -ta=tesla:cc60 -c11 -mp -Minfo -Mlarge_arrays f.o main.o -o acc.exe &&
srun -n 1 acc.exe
をコードはi
に等しい全てA[i]
要素を設定する必要がありますコンパイルする
。 OpenACCサポートでこのコードを実行すると、私は完全に間違った結果を得ます。私の推測は競争条件です。 openacc
のないバージョンが正しくコンパイルされて実行されます。 A[i]==i
ので、実行の終わりには、私の質問は:はどのように私は小さな配列がOpenACCを持つすべての GPUスレッドにプライベートであることを行うことができますか?
FYI、私はこの問題(TPRの#25047)のために、問題の報告書を提出しました。コンパイラはループ内で宣言されているので自動的に "priv"をプライベートにする必要がありますが、この場合はそうではありません。 –