在嵌套循环中使用OpenMP的性能问题
我正在使用下面的代码,它包含嵌套在另一个for-loop中的OpenMP并行for循环。 不知何故,该代码的性能比顺序版本慢4倍(省略#pragma omp parallel for)。
每次调用方法时,OpenMp是否有可能创建线程? 在我的测试中,它被直接称为10000次。
我听说有时OpenMP会保持线程旋转。 我也尝试设置OMP_WAIT_POLICY=active
和GOMP_SPINCOUNT=INFINITE
。 当我删除openMP编译指示时,代码快了大约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);
}
}
你说你的顺序代码要快得多,所以这让我认为你的processor.process
函数的指令和持续时间太少了。 这导致将数据传递给每个线程的情况没有得到回报(数据交换开销仅比该线程上的实际计算大)。
除此之外,我认为并行中间循环不会影响算法,但会增加每个线程的工作量/
我认为,要创建一个团队的线程在每次循环......(虽然我不知道是什么for
独行-我认为这应该是parallel for
)。 在这种情况下,将parallel
与for
分开可能会更好for
因此分叉和创建线程的工作只需完成一次,而不是在其他循环中重复。 因此,您可以尝试在最外层循环之前放置一个parallel
编译指示,这样分叉和线程创建的开销就会完成一次。
实际问题与OpenMP直接无关。
由于系统有两个CPU,其中一半在另一个CPU上产生,另一半在另一个CPU上产生。 因此没有共享的L3缓存。 这导致该算法不能很好地适应性能下降,尤其是在使用2-4线程时。
解决方案是使用线程锁定例如通过linux工具: taskset