【问题标题】:OpenMP results not as expectedOpenMP 结果不如预期
【发布时间】:2012-11-02 00:25:53
【问题描述】:

我有一个包含动态 3d 数组的类。类的对象调用一个函数,该函数执行一些计算来填充一维数组,最后用一维数组数据填充对象的三维数组。一维数组的大小与三维数组的大小相同。
我正在使用 Openmp 来加快计算速度。单线程执行给出了正确的结果,但是当我转到多个线程时,我得到了奇怪的结果。
示例代码如下。请帮助解决问题。

class A (
     void func(float *buf);
     void populateRes(*t); 
      private:
         float ***res;
      };

 A a[n];
 int nthrd = omp_get_num_threads();
 float *buf;
 while (cnt < nz)
 {
      #pragma omp parallel shared(cnt) private(buf, tid, omp_i)
      {
           if(cnt == 0 )
             buf = new float[x*y*z];

           #pragma omp for
           for(omp_i=0; omp_i<n; omp_i++)
           { 
              a[omp_i].func(buf);
              a[omp_i].populateRes(buf);
            }
       }
       cnt++;
       if(cnt >= nz)
          delete []buf;
   }

【问题讨论】:

    标签: c++ openmp


    【解决方案1】:

    OpenMP 不会将不同条目之间的 private 变量的值保留到同一 parallel 区域中,这与在函数的不同调用之间不会保留自动局部变量的值相同(除非它们被声明为 @987654323 @)。事实上,在大多数 OpenMP 实现中,parallel 区域是独立的函数,private 变量是自动的。

    这会使您的代码出错,因为 buf 只会在循环的第一次迭代中分配,但在下一次迭代中,您的代码将在新的 未初始化 本地副本上运行。可能发生(纯属偶然)特定线程的堆栈内容未更改,因此buf 保留其值。在parallel 区域之外删除buf 也会忽略对new 的多次调用这一事实。

    如果您只想分配一次buf,则应将while 循环放在parallel 区域内,反之亦然。这也将提高性能,因为 parallel 区域将只输入一次,并且每个条目都有相关的开销。

    A a[n];
    
    #pragma omp parallel
    {
       float *buf = new float[x*y*z];
       for (int cnt = 0; cnt < nz; cnt++)
       {
          #pragma omp for
          for (int i = 0; i < n; i++)
          {
             a[i].func(buf);
             a[i].populateRes(buf);
          }
       }
       delete [] buf;
    }
    

    (我没有看到 tid 在内部使用,所以我冒昧地将其从 private 变量列表中删除)

    可以更改两个循环的嵌套,因为for 工作共享构造的末尾有一个隐式屏障。我不知道您是否省略了其他代码,但鉴于问题中的代码,cnt 循环甚至可以嵌套在工作共享结构中,即:

    #pragma omp parallel
    {
       float *buf = new float[x*y*z];
       #pragma omp for
       for (int i = 0; i < n; i++)
       {
          for (int cnt = 0; cnt < nz; cnt++)
          {
             a[i].func(buf);
             a[i].populateRes(buf);
          }
       }
       delete [] buf;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-05
      • 2016-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多