C 具有1个线程的OpenMP比顺序版本慢

C 具有1个线程的OpenMP比顺序版本慢,c,performance,openmp,C,Performance,Openmp,我已经使用OpenMP实现了背包(gcc版本4.6.3) 定义最大值(x,y)((x)>(y)?(x):(y)) #定义表(i,j)表[(i)*(C+1)+(j)] 对于(i=1;i启用OpenMP会抑制某些编译器优化,例如,它可能会阻止循环矢量化或共享变量保留在寄存器中。因此启用OpenMP的代码通常比串行代码慢,必须利用可用的并行性来抵消这一点 这就是说,您的代码包含嵌套在外循环中的并行区域。这意味着进入和退出并行区域的开销要乘以N倍。这只有在N相对较小而C明显较大(如数量级较大)时才有意义

我已经使用OpenMP实现了背包(gcc版本4.6.3)

定义最大值(x,y)((x)>(y)?(x):(y)) #定义表(i,j)表[(i)*(C+1)+(j)]
对于(i=1;i启用OpenMP会抑制某些编译器优化,例如,它可能会阻止循环矢量化或共享变量保留在寄存器中。因此启用OpenMP的代码通常比串行代码慢,必须利用可用的并行性来抵消这一点


这就是说,您的代码包含嵌套在外循环中的并行区域。这意味着进入和退出并行区域的开销要乘以N倍。这只有在N相对较小而C明显较大(如数量级较大)时才有意义因此,在该区域内完成的工作大大超过了OpenMP开销。

启用OpenMP会抑制某些编译器优化,例如,它可能会阻止循环矢量化或共享变量保留在寄存器中。因此,启用OpenMP的代码通常比串行代码慢,必须使用可用的平行度来抵消这一点


这就是说,您的代码包含嵌套在外循环中的并行区域。这意味着进入和退出并行区域的开销要乘以N倍。这只有在N相对较小而C明显较大(如数量级较大)时才有意义因此,在该区域内所做的工作大大超过了OpenMP开销。

很可能是OpenMP开销。实际上,在使用单处理器时,并行代码永远不会比顺序代码快。顺便问一句,你确定你的测量是正确的,并且对你的尝试有重要意义吗?1s实际上是很长的时间,所以m第一个猜测是开销很小。您使用了哪些编译器选项。您是否告诉编译器优化代码(例如使用-O3、-O2或-Ofast)?我甚至尝试了15秒的运行时间,但我仍然可以看到3秒的开销。我使用-O3两种方式。很可能是OpenMP开销。事实上,在使用单处理器时,并行代码永远不会比顺序代码快。顺便问一下,你确定你的测量结果对你的尝试是正确的和重要的吗?1秒实际上是很长的时间,所以我的第一次我猜开销是微不足道的。您使用了哪些编译器选项。您是否告诉编译器优化代码(例如使用-O3、-O2或-Ofast)?我甚至尝试了15秒的运行时,但仍然可以看到3秒的开销。我两个都使用了-O3。没错,这也是我的想法。假设N足够大,那么开销应该是微不足道的。如果编译器优化产生了如此大的差异(1秒对1.7秒),我也会感到惊讶。这就是为什么我想知道是否使用了优化,以及比较有无OpenMP的程序集输出是否有趣。@Zboson,
I
是并行区域中的共享变量。GCC将该区域中
I
的任何实例转换为
omp_arg->I
,其中
omp_arg
是一个结构它包含区域中所有共享变量的副本,并将指向它的指针作为参数传递给实现该区域的函数。当以串行方式编译时,
i
很可能一直保存在寄存器中。因此,使
i
firstprivate
在一定程度上提高性能。哦,我明白你的意思了。我想因为我在并行区域没有改变,所以无论它是声明为私有还是共享都无关紧要,但我现在看到它可能会影响优化。可以使用
-O3-fdump tree all
检查
.c.126t.final_cleanup
文件,看看代码有多不同。在串行版本
i
被完全消除,而在共享版本中,
i
每次都被重新加载。@Hristo N-960,C-6680000。在这种情况下,顺序时间为16s,OpenMP和1个线程的时间为19s。因此开销约为20%。我想知道这是否正常。谢谢,这也是我的想法。假设N大于e没有那么多开销应该是微不足道的。如果编译器优化带来如此大的差异(1s与1.7s),我也会感到惊讶。这就是为什么我想知道是否使用了优化,以及比较有无OpenMP的程序集输出是否有趣。@Zboson,
I
是并行区域中的共享变量。GCC将该区域中
I
的任何实例转换为
omp_arg->I
,其中
omp_arg
是一个结构它包含区域中所有共享变量的副本,并将指向它的指针作为参数传递给实现该区域的函数。当以串行方式编译时,
i
很可能一直保存在寄存器中。因此,使
i
firstprivate
在一定程度上提高性能。哦,我明白你的意思了。我想因为我在并行区域没有改变,所以无论它是声明为私有还是共享都无关紧要,但我现在看到它可能会影响优化。可以使用
-O3-fdump tree all
检查
.c.126t.final_cleanup
文件,看看代码有多不同。在串行版本
i
被完全消除,而在共享版本中,
i
每次都被重新加载。@Hristo N-960,C-6680000。在这种情况下,顺序时间是16s,OpenMP带一个线程的时间是19s。因此开销约为20%。我想知道这是否正常。谢谢
#define MAX(x,y)   ((x)>(y) ? (x) : (y))
#define table(i,j)    table[(i)*(C+1)+(j)]

   for(i=1; i<=N; ++i) {
#pragma omp parallel for
      for(j=1; j<=C; ++j) {
         if(weights[i]>j) {
            table(i,j) = table(i-1,j);
         }else {
            table(i,j) = MAX(profits[i]+table(i-1,j-weights[i]), table(i-1,j));
         }
      }
   }