OpenMP GCC GOMP浪费的障碍

时间:2011-04-18 01:55:45

标签: 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(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);
            }
        }

然而,对于GCC 4.4,GOMP v1,gomp_barrier_wait_end占运行时间的近50%。更改GOMP_SPINCOUNT会减少开销,但只会使用60%的核心。 OMP_WAIT_POLICY=passive也是如此。该系统是Linux,8核。

如何在不旋转/等待过度的情况下获得充分利用

2 个答案:

答案 0 :(得分:3)

屏障是一种症状,而不是问题。在循环结束时有很多等待的原因是一些线程在其他线程之前完成,并且它们都在for循环结束时等待很长一段时间,直到每个人都完成了。

这是一个经典的负载不平衡问题,这里很奇怪,因为它只是一堆矩阵乘法。它们有不同的尺寸吗?就NUMA而言,它们如何在内存中布局 - 它们目前都位于一个核心的缓存中,还是存在其他共享问题?或者,更简单 - 只有9个matricies,所以剩下的8个注定要等到最后一个人的等待?

当这种事情发生在一个更大的并行代码块中时,有时可以继续执行下一个代码块,而某些循环迭代还没有完成;在那里你可以将nowait指令添加到for,它将覆盖默认行为并消除隐含的障碍。但是,由于并行块的大小与for循环的大小完全相同,因此无法提供帮助。

答案 1 :(得分:2)

你的BLAS实现是否也在内部调用OpenMP?除非你只看到一个gomp_barrier_wait_end的电话。