c - openmp 比一个线程慢,无法弄清楚

标签 c performance openmp

我遇到一个问题,我的以下代码在 openmp 下运行速度较慢:

chunk = nx/nthreads;
int i, j;
for(int t = 0; t < n; t++){
     #pragma omp parallel for default(shared) private(i, j) schedule(static,chunk) 
     for(i = 1; i < nx/2+1; i++){
        for(j = 1; j < nx-1; j++){
            T_c[i][j] =0.25*(T_p[i-1][j] +T_p[i+1][j]+T_p[i][j-1]+T_p[i][j+1]);
            T_c[nx-i+1][j] = T_c[i][j];
        }
    }
    copyT(T_p, T_c, nx);
}
print2file(T_c, nx, file);

问题是当我运行多个线程时,计算时间会长得多。

最佳答案

首先,您的并行区域会在每次外循环迭代时重新启动,从而增加巨大开销。

其次,一半的线程会坐在那里什么也不做,因为你的 block 大小是它应该的两倍 - 它是 nx/nthreads 而并行循环的迭代次数是nx/2,因此总共有(nx/2)/(nx/nthreads) = nthreads/2 block 。除了你试图实现的是复制 schedule(static) 的行为。

#pragma omp parallel
for (int t = 0; t < n; t++) {
   #pragma omp for schedule(static) 
   for (int i = 1; i < nx/2+1; i++) {
      for (int j = 1; j < nx-1; j++) {
         T_c[i][j] = 0.25*(T_p[i-1][j]+T_p[i+1][j]+T_p[i][j-1]+T_p[i][j+1]);
         T_c[nx-i-1][j] = T_c[i][j];
      }
   }
   #pragma omp single
   copyT(T_p, T_c, nx);
}
print2file(T_c, nx, file);

如果您将 copyT 修改为也使用并行 for,则应删除 single 结构。您不需要 default(shared) 因为这是默认设置。您不要将并行循环的循环变量声明为 private - 即使此变量来自外部作用域(因此在该区域中隐式共享),OpenMP 也会自动将其设为私有(private)。只需在循环控件中声明所有循环变量,它就会自动与应用的默认共享规则一起工作。

第二个半,您的内部循环中(可能)有一个错误。第二个评估声明应为:

T_c[nx-i-1][j] = T_c[i][j];

(或 T_c[nx-i][j] 如果你不在下侧保留光环)否则当 i 等于 1,那么您将访问 T_c[nx][...],它在 T_c 的范围之外。

第三,一般提示:不要将一个数组复制到另一个数组,而是使用指向这些数组的指针,并在每次迭代结束时交换两个指针。

关于c - openmp 比一个线程慢,无法弄清楚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13355559/

相关文章:

c - c中的隐式转换和显式转换

c - 压入堆栈的问题

matlab - 查找数组的等效分区

c++ - 使用 OpenMP 和 Eigen 会导致无限循环/死锁

c++ - Openmp 无法自动创建线程

c - Visual Studio 2010 的多精度

objective-c - 如何从 Objective-C 调用 C 函数

wordpress - 错误 508 - 许多 GET 请求指向不存在的路径

performance - Blob 的集群生长

asynchronous - fortran openmp 同步