openMP过度同步

时间:2017-08-18 11:40:25

标签: c++ performance optimization parallel-processing openmp

我正在尝试将openMP并行化添加到相当大的项目中,并且我发现openMP在并行块之外执行了太多同步

这个同步是针对所有变量完成的,甚至是并行块中没有使用的变量,并且不仅在进入块之前连续完成。

我做了一个证明这一点的例子:

#include <cmath>

int main()
{
    double dummy1 = 1.234;

    int const size = 1000000;
    int const size1 = 2500;
    int const size2 = 500;

    for(unsigned int i=0; i<size; ++i){

        //for (unsigned int j=0; j<size1; j++){
        //  dummy1 = pow(dummy1/2 + 1, 1.5);
        //}

        #pragma omp parallel for
        for (unsigned int j=0; j<size2; j++){
            double dummy2 = 2.345;
            dummy2 = pow(dummy2/2 + 1, 1.5);
        }
    }
}

如果我运行此代码(使用for循环注释),运行时为6.75秒,并行化,30.6秒没有。大。

但是如果我取消注释for循环并再次运行它,过度同步就会启动,我得到67.9s的并行化结果和73s没有。如果我增加size1,我甚至可以通过并行化获得比没有它更慢的结果。

有没有办法禁用此同步并仅在第二个循环之前强制它?或者其他任何方式如何提高速度?

请注意,外部并非第一个for循环都在实例中可并行化。外部实际上是一个ODE求解器,第一个内部更新内部值的载荷。

我正在使用gcc(SUSE Linux)4.8.5

感谢您的回答。

1 个答案:

答案 0 :(得分:0)

最后,我的问题的解决方案是指定线程数=处理器核心数。似乎超线程导致了这些问题。所以使用(我的处理器有4个真核)

#pragma omp parallel for num_threads(4)

我得到的时间是8.7秒而没有第一个for循环和51.9s。仍然有大约1.2s的开销,但这是可以接受的。使用默认(8个线程)

#pragma omp parallel for

时间分别为6.65s和68s。这里的开销大约是19s。

因此,如果不存在其他代码,则超线程会有所帮助,但是当它出现时,使用它可能并不总是一个好主意。