私はopenmpワークシェアリング構成を使用しようとしています。共有されたコードは、私の大きなopenmpコードで間違っていることの簡単な例です。私は整数行列に値を代入し、行列要素の値を出力し、0に初期化し、 't'ループでそれを繰り返す。私は値の代入(並列のために行われる)が整数 'p'で失敗する回数を数えています。コードが正しければ、pは0であるはずですが、異なる実行に対して私に異なる答えを与えるので、作業構造はどこかで失敗しています。出力の1,2,3などのpの最初の間違った値を得る前に、12回ぐらい実行しなければならなかった。openmpはスケジュールのために並行して実行され、いくつかのプログラムの実行に対して異なる回答を与えます
コード内のバリア指示は本当に必要ではなく、私は別の値を得ていた明白な障壁が助けになると思ったが、私は間違っていた。これはコードです:
#define NRA 10 /* number of rows in matrix A */
#define NCA 10 /* number of columns in matrix A */
int main()
{
int i, j, ir, p = 0, t;
int *a;
a = (int*) malloc(sizeof(int)*NRA*NCA);
omp_set_num_threads(5);
for(t=0;t<100000;t++)
{
#pragma omp barrier
#pragma omp parallel for schedule (static,2) collapse(2)
for(i=0;i<NRA;i++)
{
for(j=0;j<NCA;j++)
{
ir=j*NRA+i;
a[ir] = 1;
}
}
#pragma omp single
{
for(i=0;i<NRA;i++)
{
for(j=0;j<NCA;j++)
{
ir=j*NRA+i;
if(a[ir] != 1)
{
p += 1;
}
}
}
}
#pragma omp parallel for schedule (static,2) collapse(2)
for(i=0;i<NRA;i++)
{
for(j=0;j<NCA;j++)
{
ir=j*NRA+i;
a[ir] = 0;
}
}
# pragma omp barrier
}//end t
printf("p is %d\n",p);
}
これは大きなコードであり、そして私は、並列ループ内でローカル共有並列ループおよび他のすべての変数外のすべての変数を宣言したため、競合状態が問題であるとは思いません。どんな提案も役に立つでしょう!
#define NRA 10 /* number of rows in matrix A */
#define NCA 10 /* number of columns in matrix A */
#define NCB 10 /* number of columns in matrix B */
void matrixcalc (double *ad, double *bd, double *cd, int chunkd);
void printresults (double *cd, int chunkd);
void printrep (double *cd, int chunkd);
int main()
{
int nthreads, chunk, p = 0;
double *a,*b,*c;
a = (double*)malloc(NRA*NCA*sizeof(double));
if(a==NULL)
printf("ho\n");
b = (double*)malloc(NCA*NCB*sizeof(double));
c = (double*)malloc(NRA*NCB*sizeof(double));
omp_set_num_threads(5);
chunk = 2; /* set loop iteration chunk size */
int ir3, i1, j1;
/*** Spawn a parallel region explicitly scoping all variables ***/
int t, tmax = 100000;
for(t=0;t<tmax;t++)
{
#pragma omp parallel shared(a,b,c,nthreads,chunk,t,tmax)
{
int tid = omp_get_thread_num();
int i, j, ir;
if (tid == 0)
{
nthreads = omp_get_num_threads();
// printf("Starting matrix multiple example with %d threads\n",nthreads);
// printf("Initializing matrices...\n");
}
/*** Initialize matrices ***/
#pragma omp for schedule (static, chunk) collapse(2)
for (i=0; i<NRA; i++)
{
for (j=0; j<NCA; j++)
{
ir =j*NRA+i;
a[ir]= 1.0;
}
}
#pragma omp for schedule (static, chunk) collapse(2)
for (i=0; i<NCA; i++)
{
for (j=0; j<NCB; j++)
{
ir = j*NCA+i;
b[ir] = 1.0;
}
}
#pragma omp for schedule (static, chunk) collapse(2)
for (i=0; i<NRA; i++)
{
for (j=0; j<NCB; j++)
{
ir=j*NRA+i;
c[ir]= 0.0;
}
}
/*** Do matrix multiply sharing iterations on outer loop ***/
/*** Display who does which iterations for demonstration purposes ***/
matrixcalc(a,b,c,chunk);
if(t!=tmax-1)
{
#pragma omp for schedule (static, chunk) collapse(2)
for(i=0;i<NRA;i++)
{
for(j=0;j<NCB;j++)
{
ir=j*NRA+i;
c[ir]=0.0;
}
}
}
}//end parallel region
for(i1=0;i1<NRA;i1++)
{
for(j1=0;j1<NCB;j1++)
{
ir3=j1*NRA+i1;
if(c[ir3]!=12.20000&&c[ir3]!=0.0)
{
printf("%lf\n",c[ir3]);
p+=1;
}
}
}
}//end t
printf("finalp\t%d\n",p);
for(i1=0;i1<NRA;i1++)
{
for(j1=0;j1<NCB;j1++)
{
ir3=j1*NRA+i1;
printf("%lf\t",c[ir3]);
}
printf("\n");
}
}
void matrixcalc (double *a, double *b, double *c, int chunk)
{
int i,j,k,ir,ir1,ir2;
//printf("Thread %d starting matrix multiply...%d\n",tid,chunk);
double r = 1.0;
#pragma omp for schedule (static, chunk) collapse(3)
for (i=0; i<NRA; i++)
{
for(j=0; j<NCB; j++)
{
for (k=0; k<NCA; k++)
{
ir=j*NRA+i;
ir1=k*NRA+i;
ir2=j*NCA+k;
c[ir] += a[ir1] * b[ir2];
}
}
}
#pragma omp for schedule (static, chunk) collapse(2)
for(i=0;i<NRA;i++)
{
for(j=0;j<NCB;j++)
{
ir=j*NRA+i;
c[ir]+=r*2.0;
}
}
#pragma omp single
{
double h;
h = 0.1;
h = 2.0*h;
for(i=0;i<NRA;i++)
{
for(j=0;j<NCB;j++)
{
ir=j*NRA+i;
c[ir]+=h;
}
}
}
これらのバリアは、パラレルセクションの外にあるため(並列性が作成されていないため)、まったく必要ありません。さらに、 'omp single'と' omp for'はブロックの終わりに暗黙のバリアを生成します。したがって、いずれの場合も重複します。 't'ループの外側にパラレル(唯一の)コンストラクトを使用し、残りのコンストラクトでは' omp for'と 'omp single'を使います。さらに、 'i'ループと' j'ループの順序を変更して、要素を順番にアクセスする(キャッシュの局所性を向上させる)。 –
私は障壁について理解していますが、私は他の提案を書き留めました(私は理由を理解できませんでしたが)。私は並列構造をtループの外側に置こうとしましたが、コードは出力を与えるのにかなり時間がかかりました。私はプログラムを終了しなければなりませんでした。 – PooriR
あなたのエラーについて - 私は実質的に変更された質問などの完全なレビューはしませんが、並列領域内からの 'matrixcalc(a、b、c、chunk); 'の呼び出しは問題を求めています。 – Zulan