OpenMP GCC GOMP浪费屏障

OpenMP GCC GOMP浪费屏障,gcc,openmp,Gcc,Openmp,我有以下程序。 nv约为100,dgemm约为20x100,因此有大量工作要做: #pragma omp parallel for schedule(dynamic,1) for (int c = 0; c < int(nv); ++c) { omp::thread thread; matrix &t3_c = vv_.at(

我有以下程序。 nv约为100,dgemm约为20x100,因此有大量工作要做:

#pragma omp parallel for schedule(dynamic,1)
        for (int c = 0; c < int(nv); ++c) {
            omp::thread thread;                                               
            matrix &t3_c = vv_.at(omp::num_threads()+thread);
            if (terms.first) {
                blas::gemm(1, t2_, vvvo_, 1, t3_c);
                blas::gemm(1, vvvo_, t2_, 1, t3_c);
            }

            matrix &t3_b = vv_[thread];
            if (terms.second) {
                matrix &t2_ci = vo_[thread];
                blas::gemm(-1, t2_ci, Vjk_, 1, t3_c);
                blas::gemm(-1, t2_ci, Vkj_, 0, t3_b);
            }
        }
#计划的pragma omp并行(动态,1)
对于(int c=0;c
然而,在GCC4.4、GOMP v1中,
GOMP_barrier_wait_end
占运行时间的近50%。更改
GOMP_SPINCOUNT
可以减少开销,但只使用了60%的内核。同样适用于
OMP\u WAIT\u POLICY=passive
。系统为Linux,8核


如何在不旋转/等待线程的情况下充分利用资源

障碍是一种症状,而不是问题。在循环结束时有很多等待的原因是,一些线程比其他线程做得好,它们都在for循环结束时等待了相当长的时间,直到所有线程都完成

这是一个典型的负载不平衡问题,这在这里很奇怪,因为它只是一堆矩阵乘法。它们大小不一吗?在NUMA方面,它们在内存中的布局如何?它们当前都位于一个内核的缓存中,还是存在其他共享问题?或者,更简单地说,是不是只有9个婚姻,剩下的8个注定要等待最后一个结婚的人


当这类事情发生在一个较大的并行代码块中时,有时可以继续下一个代码块,而一些循环迭代尚未完成;在那里,您可以将
nowait
指令添加到for,该指令将覆盖默认行为并消除隐含的障碍。然而,在这里,由于并行块正好是for循环的大小,这并没有真正的帮助。

是否您的BLAS实现也会在内部调用OpenMP?除非您只看到一个调用
gomp\u barrier\u wait\u end

有100个矩阵,否则负载不平衡的可能性很小。虚假分享也是不可能的。nowait在速度方面会让事情变得更糟。不管是不是不太可能,如果没有负载不平衡问题,您的任务就不会在omp结束时等待。如果代码如上所述,nowait在这里也应该完全零差异;它应该只是将隐含的障碍从for的末尾转移到并行块的末尾……正如@ejd的评论所建议的,我怀疑该计划当前之所以是(动态的,1)的原因是因为默认的计划更糟糕,甚至更大的chunksize也是动态的,是吗?同样,这是负载不平衡问题的迹象。如果您的分析工具不能为您完成这些工作,那么查看情况的一种方法是为每个循环迭代计时,并用适当的线程索引和迭代次数打印出时间,然后查看是否可以找出不平衡的原因。为了好玩,请尝试将计划更改为使用“计划(静态)”看看会发生什么。@ejd也试过了,效果一样。@Anycorn:你解决问题了吗?我也有同样的问题……这绝对是一个值得研究的想法。即使使用pthreads,也可能存在一些交互。无论如何,你不应该太在意障碍(除非你的目标是减少障碍开销),但是对于你的挂钟时间:你得到的加速是什么?