如何使用MPI和OpenMP运行并行循环

时间:2019-07-04 01:19:41

标签: c parallel-processing mpi openmp

我需要使用MPI和OpenMP(两个不同的问题)来并行化Sbac-Pad马拉松比赛的代码(参考:http://lspd.mackenzie.br/marathon/18/problems.html)。我正在研究himeno基准。我相信该代码中唯一值得并行化的部分是jacobi函数:

#define MR(mt,n,r,c,d)  mt->m[(n) * mt->mrows * mt->mcols * mt->mdeps + (r) * mt->mcols* mt->mdeps + (c) * mt->mdeps + (d)]

struct Matrix {
  float* m;
  int mnums;
  int mrows;
  int mcols;
  int mdeps;
};

float
jacobi(int nn, Matrix* a,Matrix* b,Matrix* c,
       Matrix* p,Matrix* bnd,Matrix* wrk1,Matrix* wrk2)
{
  int    i,j,k,n,imax,jmax,kmax;
  float  gosa,s0,ss;

  imax= p->mrows-1;
  jmax= p->mcols-1;
  kmax= p->mdeps-1;

  for(n=0 ; n<nn ; n++){
    gosa = 0.0;
    for(i=1 ; i<imax; i++)
      for(j=1 ; j<jmax ; j++)
        for(k=1 ; k<kmax ; k++){
          s0= MR(a,0,i,j,k)*MR(p,0,i+1,j,  k)
            + MR(a,1,i,j,k)*MR(p,0,i,  j+1,k)
            + MR(a,2,i,j,k)*MR(p,0,i,  j,  k+1)
            + MR(b,0,i,j,k)
             *( MR(p,0,i+1,j+1,k) - MR(p,0,i+1,j-1,k)
              - MR(p,0,i-1,j+1,k) + MR(p,0,i-1,j-1,k) )
            + MR(b,1,i,j,k)
             *( MR(p,0,i,j+1,k+1) - MR(p,0,i,j-1,k+1)
              - MR(p,0,i,j+1,k-1) + MR(p,0,i,j-1,k-1) )
            + MR(b,2,i,j,k)
             *( MR(p,0,i+1,j,k+1) - MR(p,0,i-1,j,k+1)
              - MR(p,0,i+1,j,k-1) + MR(p,0,i-1,j,k-1) )
            + MR(c,0,i,j,k) * MR(p,0,i-1,j,  k)
            + MR(c,1,i,j,k) * MR(p,0,i,  j-1,k)
            + MR(c,2,i,j,k) * MR(p,0,i,  j,  k-1)
            + MR(wrk1,0,i,j,k);

          ss= (s0*MR(a,3,i,j,k) - MR(p,0,i,j,k))*MR(bnd,0,i,j,k);

          gosa+= ss*ss;
          MR(wrk2,0,i,j,k)= MR(p,0,i,j,k) + omega*ss;
        }

    for(i=1 ; i<imax ; i++)
      for(j=1 ; j<jmax ; j++)
        for(k=1 ; k<kmax ; k++)
          MR(p,0,i,j,k)= MR(wrk2,0,i,j,k);

  } /* end n loop */

  return(gosa);
}

问题是,此功能似乎具有顺序性质,因为nn的每次迭代都依赖于最后一个。我尝试使用MPI为gosaauxgosa)创建一个辅助变量,并在i j k for循环之后使用MPI_REDUCE,如下所示(根进程的等级为0):

//rank is the current process
//size is the total amount of processes

int start = ((imax+1)/size)*rank; 
int stop = ((imax+1)/size)*(rank+1)-1;

  if(rank == 0){start++;}

  for(n=0 ; n<nn ; n++){
    gosa = 0.0;
    auxgosa = 0.0;

    for(i=start ; i<stop; i++)
      for(j=1 ; j<jmax ; j++)
        for(k=1 ; k<kmax ; k++){
          s0= MR(aa,0,i,j,k)*MR(pp,0,i+1,j,k)
            + MR(aa,1,i,j,k)*MR(pp,0,i,  j+1,k)
            + MR(aa,2,i,j,k)*MR(pp,0,i,  j,  k+1)
            + MR(bb,0,i,j,k)
             *( MR(pp,0,i+1,j+1,k) - MR(pp,0,i+1,j-1,k)
              - MR(pp,0,i-1,j+1,k) + MR(pp,0,i-1,j-1,k) )
            + MR(bb,1,i,j,k)
             *( MR(pp,0,i,j+1,k+1) - MR(pp,0,i,j-1,k+1)
              - MR(pp,0,i,j+1,k-1) + MR(pp,0,i,j-1,k-1) )
            + MR(bb,2,i,j,k)
             *( MR(pp,0,i+1,j,k+1) - MR(pp,0,i-1,j,k+1)
              - MR(pp,0,i+1,j,k-1) + MR(pp,0,i-1,j,k-1) )
            + MR(cc,0,i,j,k) * MR(pp,0,i-1,j,  k)
            + MR(cc,1,i,j,k) * MR(pp,0,i,  j-1,k)
            + MR(cc,2,i,j,k) * MR(pp,0,i,  j,  k-1)
            + MR(awrk1,0,i,j,k);

          ss= (s0*MR(aa,3,i,j,k) - MR(pp,0,i,j,k))*MR(abnd,0,i,j,k);

          auxgosa+= ss*ss;
          MR(awrk2,0,i,j,k)= MR(pp,0,i,j,k) + omega*ss;
        }

    MPI_Reduce(&auxgosa,&gosa,1,MPI_FLOAT,MPI_SUM,0,MPI_COMM_WORLD);

    for(i=1 ; i<imax ; i++)
      for(j=1 ; j<jmax ; j++)
        for(k=1 ; k<kmax ; k++)
          MR(pp,0,i,j,k)= MR(awrk2,0,i,j,k);

  } /* end n loop */

不幸的是,这没有用。谁能给我一些有关此的见解?我计划对OpenMP使用类似的策略。

1 个答案:

答案 0 :(得分:0)

如果awrk2apbcwrk1不同,则不存在循环携带依赖性。

简单的google搜索将为您指向Himeno基准测试的并行版本(提供MPI,OpenMP和MPI + OpenMP混合版本)。