【问题标题】:OpenMP parallelization not efficientOpenMP 并行化效率不高
【发布时间】:2016-01-22 01:42:10
【问题描述】:

我正在尝试使用 OpenMP 并行化此代码。

for(t_step=0;t_step<Ntot;t_step++) {
        // current row
        if(cur_row + 1 < Npt_x)     cur_row++; 
        else                        cur_row = 0;
        // get data from file which update only the row "cur_row" of array val
        read_line(f_u, val[cur_row]);
        // computes
        for(i=0;i<Npt_x;i++) {
            for(j=0;j<Npt_y;j++) {
                i_corrected = cur_row - i;
                if(i_corrected < 0)     i_corrected = Npt_x + i_corrected;
                R[i][j] += val[cur_row][0]*val[i_corrected][j]/Ntot;
            }
        }
    }


- val 和 R 声明为 **double,
- Npt_x 和 Npt_y 大约是 500,
- Ntot 约为 10^6。

我已经做到了

for(t_step=0;t_step<Ntot;t_step++) {
        // current row
        if(cur_row + 1 < Npt_x)     cur_row++; 
        else                        cur_row = 0;
        // get data from file which update only the row "cur_row" of array val
        read_line(f_u, val[cur_row]);
        // computes
        #pragma omp parallel for collapse(2), private(i,j,i_corrected)
        for(i=0;i<Npt_x;i++) {
            for(j=0;j<Npt_y;j++) {
                i_corrected = cur_row - i;
                if(i_corrected < 0)     i_corrected = Npt_x + i_corrected;
                R[i][j] += val[cur_row][0]*val[i_corrected][j]/Ntot;
            }
        }
    }

问题是它似乎没有效率。在这种情况下,有没有办法更有效地使用 OpenMP?

多谢

【问题讨论】:

标签: c multithreading for-loop parallel-processing openmp


【解决方案1】:

现在,我会尝试这样的事情:

for(t_step=0;t_step<Ntot;t_step++) {
    // current row
    if(cur_row + 1 < Npt_x)
        cur_row++; 
    else
        cur_row = 0;
    // get data from file which update only the row "cur_row" of array val
    read_line(f_u, val[cur_row]);
    // computes
    #pragma omp parallel for private(i,j,i_corrected)
    for(i=0;i<Npt_x;i++) {
        i_corrected = cur_row - i;
        if(i_corrected < 0)
            i_corrected += Npt_x;
        double tmp = val[cur_row][0]/Ntot;
        #if defined(_OPENMP) && _OPENMP > 201306
        #pragma omp simd
        #endif
        for(j=0;j<Npt_y;j++) {
            R[i][j] += tmp*val[i_corrected][j];
        }
    }
}

但是,由于代码将受内存限制,因此不确定它是否会大大提高并行速度...不过值得一试。

【讨论】:

  • +1 巧妙地使用#pragma omp simd(OpenMP 4.0 imo 的最佳特性),以及巧妙的重组以避免重新计算。不幸的是 OP - 这个程序的绝大多数执行时间可能都在调用read_line(),这不是线程安全的。我无法想象并行化可以显着改进这个程序。
  • @NoseKnowsAll,有趣的是,您认为#pragma omp simd 是 OpenMP 4.0 最有趣的功能,因为我发现它至少对 x86 编译器几乎没用。也许它在其他架构上有意义,但主要的 x86 C/C++ 编译器已经很好地进行了自动矢量化,而那些不支持 OpenMP 4.0 的编译器无论如何也不支持。
  • 有了这个解决方案,它在 16 个内核上的运行速度提高了 25%(我没有尝试使用更少的内核)。但正如@NoseKnowsAll 所提到的,大部分执行都花在函数read_line() 中。所以我不认为我可以得到更多的改进。
  • @Zboson 在我最近的波传播算法中,它将运行时间提高了 50% 以上。自动矢量化显然看不到很多可用的并行化。在我看来,它比替代的特定于编译器的编译指示更清晰/更强大。
  • @NoseKnowsAll,这很有趣。我想知道为什么。我怀疑这是由于关联数学。您是否尝试过使用-Ofast?实际上,这是我能想到的唯一一个 omp simd 有用的地方。它允许您选择要使用关联数学完成的循环,而无需为整个翻译单元启用-Ofast。如果 OpenMP 有一个 unroll 构造它,例如#pragma omp simd unroll(8)展开八次,会更有趣。
猜你喜欢
  • 2012-06-27
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
相关资源
最近更新 更多