在嵌套循环中使用 OpenMP 的性能问题

Performance problems using OpenMP in nested loops

我正在使用以下代码,其中包含嵌套在另一个 for 循环中的 OpenMP 并行 for 循环。这段代码的性能不知何故比顺序版本慢 4 倍(省略#pragma omp parallel for)。

有没有可能每次调用方法时OpenMp都要创建Threads?在我的测试中它被直接调用了10000次。

我听说有时 OpenMP 会使线程保持旋转。我还尝试设置 OMP_WAIT_POLICY=activeGOMP_SPINCOUNT=INFINITE。当我删除 openMP pragmas 时,代码速度大约快 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) .在这种情况下,最好将 parallelfor 分开,这样分叉和创建线程的工作只完成一次,而不是在其他循环中重复。因此,您可以尝试在最外层循环之前放置一个 parallel 编译指示,这样分叉和线程创建的开销就只完成一次。

实际问题与 OpenMP 没有直接关系。

由于系统有两个 CPU,一半的线程在一个上生成,另一半在另一个 CPU 上生成。因此没有共享的 L3 缓存。这导致算法不能很好地扩展到性能下降的组合,尤其是在使用 2-4 个线程时。

解决方案是通过 linux 工具使用螺纹固定:taskset