【问题标题】:OpenMP low performanceOpenMP 性能低下
【发布时间】:2015-09-29 11:22:55
【问题描述】:

我试图在我的程序中并行化一个循环,所以我搜索了多线程。首先我看了一下 POSIX 多线程编程教程,它太复杂了,所以我试着做一些更简单的事情。我尝试使用 OpenMP。我已经成功地并行化了我的代码,但执行时间问题比串行情况更糟。这是我的程序的一部分。我希望你告诉我有什么问题。我应该指定哪些变量是共享的,哪些是私有的?我怎么知道每个变量的种类?我希望你能回答我,因为我搜索了很多论坛,但我仍然不知道该怎么做。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <omp.h>
#define D                0.215         // magnetic dipolar constant

main()
{
  int     i,j,n,p,NTOT = 1600,Nc = NTOT-1;
  float   r[2],spin[2*NTOT],w[2],d;
  double  E,F,V,G,dU;
  .
  .
  .
  for(n = 1; n <= Nc; n++){
    fscanf(voisins,"%d%d%f%f%f",&i,&j,&r[0],&r[1],&d);
    V = 0.0;E = 0.0;F = 0.0;
    #pragma omp parallel num_threads(4)
    {
      #pragma omp for schedule(auto)
      for(p = 0;p < 2;p++)
      {
        V += (D/pow(d,3.0))*(spin[2*i-2+p]-w[p])*spin[2*j-2+p];
        E += (spin[2*i-2+p]-w[p])*r[p];
        F += spin[2*j-2+p]*r[p];
      }
    }
    G = -3*(D/pow(d,5.0))*E*F;
    dU += (V+G);
   }
   .
   .
   .
 }//End of main()

【问题讨论】:

  • 执行时间问题比串行情况更糟 这通常是由于使用了错误的时序例程造成的。您的代码没有显示您正在使用的内容,最好确保它是omp_get_wtime

标签: c openmp


【解决方案1】:

您正在并行化一个只有 2 次迭代的循环:p=0p=1。 OpenMP 的omp for 的工作方式是将循环迭代在并行团队(您已定义为 4 个线程)中的线程之间拆分,并让它们并行解决问题的一部分。

只有 2 次迭代,您的 2 个线程将处于空闲状态。最重要的是,实际上要弄清楚哪些线程将处理问题的哪一部分需要开销。如果您的实际循环不需要很长时间(在这种情况下显然不需要),那么开销将超过您从并行化中获得的好处。

更好的策略通常是尽可能使用 OpenMP 并行化最外层循环,以解决平均分配工作和减少(相对)开销的问题。或者,您可以使用 OpenMP 4.0 的 omp simd 命令在最低循环级别进行并行化。

最后,您没有正确计算变量VEF。因为它们是从迭代到迭代的总和,所以您应该使用reduction(+:V) 将它们全部定义为归约变量。如果您目前按原样得到正确答案,我会感到惊讶。

(也正如高性能标记所说:确保您正在计时程序的墙上时间执行而不是程序的 CPU 时间执行。这通常使用 omp_get_wtime() 完成。)

【讨论】:

  • 谢谢鼻子的回答,我认为这很有帮助。我绑定到并行化外循环,但在这种情况下,顶部的 CPU 活动显示 45% 专用于我们,15% 用于 sy,40% 用于 id,这不是我并行化内循环时的情况(99% 用于我们)。我确实理解你所说的两个空闲线程,但时间问题仍然存在。你认为我应该说哪些变量是共享的,哪些是私有的以避免竞争条件?
  • OpenMP 的默认设置是每个变量都是共享的。在这种情况下并行化你的内循环时,你只需要指定VEF是归约变量,p是私有的。
  • 并行化你的外循环(我相信这是要走的路)需要#pragma omp parallel for private(n, V, E, F, p, G) reduction(+:dU) num_threads(4)
  • 另外,仅供参考:当您从 Linux 命令行运行 top 时,您应该会看到 4 个线程以接近 100% 的速度运行(或者有时您将其视为 1 个“线程”以 400% 的速度运行)。您只看到 45% 的事实意味着您可能没有正确设置系统。运行单线程版本的代码是什么意思?
  • 对不起鼻子,我只是有点困惑。我尝试#pragma omp parallel for private(n, V, E, F, p, G) reduction(+:dU) num_threads(4) 并且同样的问题仍然存在。它总是这样 CPU0 45%us CPU1 45%us CPU2 45%us CPU3 45%us...但是当我输入 num_threads(1) 时它是 CPU3 100%us, 0%id 其余的 0%us, 99%id就像连环案一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 2011-11-03
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多