并行两个嵌套的for-循环,我遇到了我无法解释的行为。我在OpenMP 860和xeon E5540上尝试了三种不同类型的并行化,我希望代码在这两个平台上的行为大致相同,这意味着对于我测试的所有三种不同的情况,其中一个平台应该更快。但情况并非如此:
因子。
你知道是什么导致的吗?
请说明您何时需要更多的信息或澄清!
为了进一步澄清,我的问题意味着更笼统。如果我在i7和xeon系统上运行相同的代码,那么使用OpenMP不应该产生可比较的(比例的)结果吗?
伪码:
for 1:4
for 1:1000
vector_multiplication
end
end的案例:
案例1:没有pramga omp没有并行化
案例2:第一个for -循环的pragma omp
案例3:第二个for -循环的pragma omp
结果
下面是time命令中的实际数字:
案例1
Time Xeon i7
real 11m14.120s 12m53.679s
user 11m14.030s 12m46.220s
sys 0m0.080s 0m0.176s案例2
Time Xeon i7
real 8m57.144s 4m37.859s
user 71m10.530s 29m07.797s
sys 0m0.300s 0m00.128s案例3
Time Xeon i7
real 2m00.234s 3m35.866s
user 11m52.870s 22m10.799s
sys 0m00.170s 0m00.136s更新
谢谢你的提示。我还在研究原因是什么。
发布于 2010-11-03 21:42:45
这里已经有了很好的答案,关于编译效果的可能变化,等等,这是非常正确的;但是还有其他的理由来期待差异。像这样简单明了(例如,低算术强度)的计算往往对内存带宽非常敏感;每个线程可用内存带宽的数量将取决于您运行的线程数。在这两个系统上,内存的设置是否都是相同的?
看起来i7 860的时钟速度更快,但E5540的总内存带宽更高。由于case 2只能使用4个线程,而case 3可以使用更多的线程,因此认为在4线程情况下时钟速度获胜并不疯狂,但是在8线程情况下,增加的内存争用(8个线程试图拉入/推送值)将手指向高带宽的Xeon。
更复杂的是,看起来你在运行8个线程--这些是双套接字系统,还是你在使用超线程?这使得情况更加复杂,因为超线程实际上帮助隐藏了一些内存争用,在另一个线程等待内存时切换到线程中。
如果你想看看有限内存带宽是否在这里起作用,你可以人为地给问题增加更多的计算(例如,把exp(sin(a))乘以cos(b)*cos(b)或其他什么东西),以确保问题是计算界的,当你试图找出问题的根源时,可以去掉一个变量。在每个系统上编译代码,并对该特定机器进行优化(使用-march或-xHost或其他什么)消除了另一个变量。如果超线程打开,关闭它(或者仅仅将OMP_NUM_THREADS设置为物理内核的数量)就会删除另一个变量。一旦你了解了在这个简化的情况下发生了什么,一个接一个地放松上面的限制会帮助你更好地理解正在发生的事情。
发布于 2010-11-03 14:52:55
影响openMP效率的因素是迭代界的计算。确保这些都是事先计算出来的,并且迭代变量尽可能是局部的。如果你让C99做类似的事情
#pragma omp parallel for
for (size_t i = start, is = stop; i < is; ++i) ...以确保表达式start和stop在开始时得到计算。(或者使用_Pragma,请参阅我的另一个答案。)
那么唯一的方法是查看汇编程序代码(通常是选项-S),以确定它是否真的成功。
如果没有查看其他编译器选项。gcc有一个选项-march=native,它为实际的体系结构进行优化编译。其他平台也可能有类似的选择。从为案例1搜索最佳架构选项开始。
发布于 2010-11-03 16:32:57
这与其说是回答,不如说是评论。
还不完全清楚你测量的是什么。为了获得更大的确定性,我想:
撇开这一切不说,我倾向于同意你的初步结果需要进一步调查。
我建议您尝试的一件事是折叠您的两个循环,让OpenMP调度4000循环而不是4或1000循环。
https://stackoverflow.com/questions/4087094
复制相似问题