C 具有1个线程的OpenMP比顺序版本慢
我已经使用OpenMP实现了背包(gcc版本4.6.3) 定义最大值(x,y)((x)>(y)?(x):(y)) #定义表(i,j)表[(i)*(C+1)+(j)]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明显较大(如数量级较大)时才有意义
对于(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));
}
}
}