我使用以下代码,其中包含一个嵌套在另一个for循环中的OpenMP并行for循环。不知何故,这段代码的性能比顺序版慢4倍(省略#pragma omp parallel for)。
每次调用方法时OpenMp都有可能创建线程吗?在我的测试中,它直接被称为10000次。
我听说OpenMP会让线程保持旋转状态。我还尝试设置OMP_WAIT_POLICY=active
和GOMP_SPINCOUNT=INFINITE
。当我删除openMP pragma时,代码大约快10倍。请注意,包含此代码的方法将被调用10000次。
for (round k = 1; k < processor.max; ++k) {
initialise_round(k);
for (std::vector<int> bucket : color_buckets) {
#pragma omp parallel for schedule (dynamic)
for (int i = 0; i < bucket.size(); ++i) {
if (processor.mark.is_marked_item(bucket[i])) {
processor.process(k, bucket[i]);
}
}
processor.finish_round(k);
}
}
答案 0 :(得分:2)
你说你的顺序代码要快得多,所以这让我认为你的processor.process
函数的指令和持续时间太少了。这导致将数据传递到每个线程的情况不会得到回报(数据交换开销仅比该线程上的实际计算大)。
除此之外,我认为并行化中间循环不会影响算法,但会增加每个线程的工作量/
答案 1 :(得分:0)
我认为你是在循环的每次迭代中创建一个线程团队......(虽然我不确定for
单独做什么 - 我认为它应该是parallel for
)。在这种情况下,将parallel
与for
分开可能会更好,因此分叉和创建线程的工作只需执行一次,而不是在其他循环中重复。因此,您可以尝试在最外层循环之前放置parallel
pragma,这样就可以完成分叉和创建线程的开销一次。
答案 2 :(得分:0)
实际问题与OpenMP没有直接关系。
由于系统有两个CPU,一半的线程在另一个CPU上生成,另一半在另一个CPU上生成。因此没有共享L3缓存。这导致该算法无法很好地扩展到性能下降,尤其是在使用2-4个线程时。
解决方案是使用线程固定,例如通过linux工具:taskset