モデルのデータを保持し、そのデータに対していくつかの関数を実行するModelクラスがあります。詳細はおそらくそれほど重要ではないが、以下のデザインを有する。` - >`のループ依存依存は並列化を防ぎます
- 変数はクラス名前空間に格納される。
- 変数は、クラスのメソッドのいずれかによって初期化され、解放されます。
- 変数は他のいくつかの方法で使用されます。次のようにクラスの
A MWEが表示されます。
#include <cstdlib>
class Model {
private:
int width;
int height;
int size;
int nshift[8]; //Offset from a focal cell's index to its neighbours
double *restrict h; //Digital elevation model (height)
int *restrict rec; //Index of receiving cell
const int NO_FLOW = -1;
const double SQRT2 = 1.414213562373095048801688724209698078569671875376948;
const double dr[8] = {1,SQRT2,1,SQRT2,1,SQRT2,1,SQRT2};
private:
void GenerateRandomTerrain(){
//srand(std::random_device()());
for(int y=0;y<height;y++)
for(int x=0;x<width;x++){
const int c = y*width+x;
h[c] = rand()/(double)RAND_MAX;
}
}
public:
Model(const int width0, const int height0)
: nshift{-1,-width0-1,-width0,-width0+1,1,width0+1,width0,width0-1}
{
width = width0;
height = height0;
size = width*height;
h = new double[size];
GenerateRandomTerrain();
}
~Model(){
delete[] h;
}
private:
void FindDownstream(){
//! computing receiver array
#pragma acc parallel loop collapse(2) independent present(h,rec,width,height)
for(int y=2;y<height-2;y++)
for(int x=2;x<width-2;x++){
const int c = y*width+x;
//The slope must be greater than zero for there to be downhill flow;
//otherwise, the cell is marekd NO_FLOW
double max_slope = 0;
int max_n = NO_FLOW;
#pragma acc loop seq
for(int n=0;n<8;n++){
double slope = (h[c] - h[c+nshift[n]])/dr[n];
if(slope>max_slope){
max_slope = slope;
max_n = n;
}
}
rec[c] = max_n;
}
}
public:
void run(const int nstep){
rec = new int[size];
#pragma acc enter data copyin(h[0:size],nshift[0:8],height,width,this) create(rec[0:size])
for(int step=0;step<=nstep;step++)
FindDownstream();
#pragma acc exit data copyout(h[0:size]) delete(this,rec)
delete[] rec;
}
};
int main(int argc, char **argv){
Model model(300,300);
model.run(100);
return 0;
}
私が使用してコンパイル:
pgc++ -acc -ta=tesla,pinned,cc60 -Minfo=accel -fast test.cpp -std=c++11
私は、取得するには、次の警告:一部の掘り
51, Loop without integer trip count will be executed in sequential mode
Complex loop carried dependence of rec->,nshift prevents parallelization
Loop carried dependence of rec-> prevents parallelization
Loop carried backward dependence of rec-> prevents vectorization
インターネットは、これの典型的な原因がpointeの可能性であることを明らかにする依存関係を引き起こすエイリアシング。
私は*restrict
とindependent
(ここに示す)を使用して、コンパイラにすべて正しいものを伝えようとしましたが、私を無視してループを並列化しません。
restrict
を適切に使用して関数に引数としてポインタを渡すと、エラーはなくなりますが、私はこのデザインに対して美的な好みがあります。あるいは、本質的にカーネルであるすべてのメソッドは、関数run()
で一緒につなぐことができますが、これも望ましくありません。
私は内側のループにindependent
を使用している場合は、私が手:
PGCC-W-0155-内側のループは、ループの入れ子は、別のループディレクティブ(227 actual_code.cpp)を持つべきではない崩壊
しかし、ループは並列化されているように見えます。
PGI 17.9でコンパイルしています。
ありがとう、マット!それは意味をなさないが、それは確かに私がコンパイラの出力から取り除いたものではない: 'rec - >、nshift 'の言及は修正が必要な問題のように思えた。もしコンパイラが 'height'と' width'が揮発性であるかもしれないと思っているのであれば、コンパイラが何らかの形でそれを識別できれば涼しいでしょう。 – Richard
主なメッセージは、高さと幅が揮発性であるためにカウントできないループに関するものです。 "rec->"依存性は、計算されたインデックスの使用によって引き起こされます。あなたは "並列ループ"を使用しているので、コンパイラは依存関係を無視します。 –