Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C OpenMP低性能_C_Openmp - Fatal编程技术网

C OpenMP低性能

C OpenMP低性能,c,openmp,C,Openmp,我试图在我的程序中并行化一个循环,所以我搜索了多线程。首先我看了一下POSIX多线程编程教程,它太复杂了,所以我试着做一些简单的事情。我试过使用OpenMP。我已经成功地将代码并行化了,但是执行时间的问题比串行情况更严重。这是我的程序下面的一部分。我希望你告诉我有什么问题。我应该指定哪些变量是共享的,哪些是私有的吗?我怎么知道每个变量的类型?我希望你回答我,因为我在很多论坛上搜索,我仍然不知道该怎么办 #include <stdio.h> #include <math.h>

我试图在我的程序中并行化一个循环,所以我搜索了多线程。首先我看了一下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()
#包括
#包括
#包括
#包括
#包括
#定义d0.215//磁偶极常数
main()
{
int i,j,n,p,NTOT=1600,Nc=NTOT-1;
浮动r[2],自旋[2*NTOT],w[2],d;
双E,F,V,G,dU;
.
.
.

对于(n=1;n而言,您正在以2次迭代并行化一个循环:
p=0
p=1
。OpenMP的
omp for
工作方式是在并行团队中的线程(您定义为4个线程)之间拆分循环迭代,并让它们并行处理问题的各个部分

只进行2次迭代,就有2个线程处于空闲状态。除此之外,实际计算出哪些线程将处理问题的哪一部分会带来开销。如果实际循环不会花费很长时间(在本例中显然不会),那么开销将比并行化带来的好处更高

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

最后,您没有正确地计算变量
V
E
F
。因为它们是从一个迭代到另一个迭代求和的,所以您应该使用
reduce(+:V)
将它们定义为缩减变量。如果您目前得到的答案是正确的,我会感到惊讶


(同样正如High Performance Mark所说:确保您正在计时程序的墙时间执行,而不是程序的CPU时间执行。这通常是通过
omp\u get\u wtime()
完成的)

执行时间问题比串行情况更严重这通常是由于使用错误的计时例程造成的。你的代码没有显示你在使用什么,最好确保它是
omp_get_wtime
。谢谢你的回答,我认为这很有帮助。我想并行化外循环,但在这种情况下,顶部的CPU活动显示45%用于我们,15%用于sy,40%用于id,这与我并行化内循环时的情况不同(美国为99%)。我确实理解你所说的关于两个空闲线程的内容,但时间问题仍然存在。你认为我应该说哪些变量是共享的,哪些是私有的,以避免争用条件?OpenMP的默认设置是每个变量都是共享的。在这种情况下,并行内部循环时,你只需要指定
V
E
F
是缩减变量,而
p
是私有的。并行化您的外循环(我认为这是一个方向)将需要
#pragma omp parallel for private(n,V,E,F,p,G)缩减(+:dU)num_threads(4)
另外,仅供参考:您应该看到4个线程以接近100%的速度运行(或者有时您将其视为1个“thread”从Linux命令行运行
top
时以400%的速度运行。事实上,您只看到45%的速度,这意味着您可能没有正确设置系统。当您运行单线程版本的代码时,它会说什么?抱歉,我只是有点困惑。我尝试了“pragma omp parallel for private(n,V,E,F,p,G)减少(+:dU)num_线程(4),同样的问题仍然存在。它总是像这样的CPU0 45%us CPU1 45%us CPU2 45%us CPU3 45%us…但是当我放置num_线程(1)时,它是CPU3 100%us,0%id,其余的0%us,99%id,就像串行情况一样。