使用C语言为OpenMP创建函数线程安全

时间:2010-10-26 17:38:10

标签: c thread-safety openmp

我有一个函数可以确定是否需要对数组进行平滑处理。我有多个数组需要执行此操作。我想在OpenMP中使用sections构造来执行此操作。不幸的是,一旦代码增长到可观的大小,我就会遇到分段错误。这可能是内存限制问题,但我想要你的输入。 这是调用函数的伪代码:

#pragma omp parallel default(shared) private(i,j,k,memd,memi,mdpmi,mdpme,mipmn,mipmn,mdinv,meinv,miinv,mimime,memime,gchk,spat,dtinv,mtempx,mtempy,mtempz,mtempinv) \
                     firstprivate(memd,memi,mdpmi,mdpme,mipmn,mipmn,mdinv,meinv,miinv,mimime,memime,gchk,spat,dtinv)
{
.
.
.
  #pragma omp single
  printf("----- Check for smoothing -----\n");
  #pragma omp sections
  {
    //Grids are now at the same timestep so we smooth
    #pragma omp section
    {
      printf("-----   Smoothing of Rho by TID:%d\n",omp_get_thread_num());
      smooth(mhd->rho,mhd->rhosmo,grid,omp_get_thread_num());
    }
    #pragma omp section
    {
      printf("-----   Smoothing of Rhoi by TID:%d\n",omp_get_thread_num());
      smooth(mhd->rhoi,mhd->rhoismo,grid,omp_get_thread_num());
    }
    .
    .
    .
  } /*-- End of Sections --*/
  .
  .
  .
} /*-- End of Parallel Region --*/

现在功能看起来像这个

void smooth(double ***field,char ***tsmooth,GRID *grid,int tid)
{
  double mtempx[grid->nx][grid->ny][grid->nz];
  double mtempy[grid->nx][grid->ny][grid->nz];
  double mtempz[grid->nx][grid->ny][grid->nz];
  double mtempinv;
  double etol=1e-10;  //Oscillation amplitude tollerance
  double itol=1e-2;   //Inverse tollerance
  for(i=0;i<grid->nx;i++)
  {
    for(j=0;j<grid->ny;j++)
    {
      for(k=0;k<grid->nz;k++)
        {
          printf("-----  SMOOTH(TID:%2d) i=%3d j=%3d k=%3d\n",tid,i,j,k);
          mtempx[i][j][k]=0.0;
          mtempy[i][j][k]=0.0;
          mtempz[i][j][k]=0.0;
          tsmooth[i][j][k]=0;
        }
    }
  }
  for(i=1;i<grid->nx-1;i++)
  {
    for(j=1;j<grid->ny-1;j++)
    {
      for(k=1;k<grid->nz-1;k++)
      {
        mtempinv=1.;
        if (sqrt(field[i][j][k]*field[i][j][k]) > itol) mtempinv=1./field[i][j][k];
        mtempx[i][j][k]=(field[i+1][j][k]-field[i][j][k])*(field[i][j][k]-field[i-1][j][k]);
        mtempy[i][j][k]=(field[i][j+1][k]-field[i][j][k])*(field[i][j][k]-field[i][j-1][k]);
        mtempz[i][j][k]=(field[i][j][k+1]-field[i][j][k])*(field[i][j][k]-field[i][j][k-1]);
        if (sqrt(mtempx[i][j][k]*mtempx[i][j][k])*mtempinv*mtempinv <= etol) mtempx[i][j][k]=0.0;
        if (sqrt(mtempy[i][j][k]*mtempy[i][j][k])*mtempinv*mtempinv <= etol) mtempy[i][j][k]=0.0;
        if (sqrt(mtempz[i][j][k]*mtempz[i][j][k])*mtempinv*mtempinv <= etol) mtempz[i][j][k]=0.0;
      }
    }
  }
  for(i=1;i<grid->nx-1;i++)
  {
    for(j=1;j<grid->ny-1;j++)
    {
      for(k=1;k<grid->nz-1;k++)
      {
        if (   ((mtempx[i][j][k] < 0.0) && ((mtempx[i+1][j][k] < 0.0)||(mtempx[i-1][j][k] < 0.0))) 
                || ((mtempy[i][j][k] < 0.0) && ((mtempy[i][j+1][k] < 0.0)||(mtempy[i][j-1][k] < 0.0)))
                || ((mtempz[i][j][k] < 0.0) && ((mtempz[i][j][k+1] < 0.0)||(mtempx[i][j][k-1] < 0.0)))) tsmooth[i][j][k]=1;
      }
    }
  }

}

现在这在串行和数组101x7x49中运行良好似乎工作正常但是当我去389x7x739的数组时,我可以通过函数中的第一个printf语句。注意我只添加了printf语句来帮助理解发生了什么。这不应该是线程安全的吗?

1 个答案:

答案 0 :(得分:1)

临时矩阵(mtempx,mtempy等)需要比系统堆栈提供的空间更多的空间。相反,动态分配这些缓冲区(或静态地将它们声明为固定大小)。