C++ 更好地使用openmp

C++ 更好地使用openmp,c++,openmp,C++,Openmp,我正在尝试实现openMP,但就像我之前的许多海报一样,结果只是代码速度变慢了。受前面答案的启发,我从使用#pragma omp parallel for改为#pragma omp task,希望能避免一些开销。不幸的是,并行化代码的速度仍然是串行代码的两倍。从其他答案来看,正确的程序似乎取决于代码的具体要求,这就是为什么我认为我必须自己问一个问题 首先是伪代码: #pragma omp parallel { #pragma omp master while (will be run some

我正在尝试实现openMP,但就像我之前的许多海报一样,结果只是代码速度变慢了。受前面答案的启发,我从使用
#pragma omp parallel for
改为
#pragma omp task
,希望能避免一些开销。不幸的是,并行化代码的速度仍然是串行代码的两倍。从其他答案来看,正确的程序似乎取决于代码的具体要求,这就是为什么我认为我必须自己问一个问题

首先是伪代码:

#pragma omp parallel
{
#pragma omp master
while (will be run some hundreds of millions of times)
{
    for (between 5 and 20 iterations)
    {
        #pragma omp task
        (something)
    }
    #pragma omp taskwait <- it is important that all the above tasks are completed before going on

    (something)

    if (something)
    {
        (something)

        for (between 50 and 200 iterations)
        {
            #pragma omp task 
            (something)
        }
        #pragma omp taskwait

        (something)
    }

}
}
#pragma omp并行
{
#pragma-omp-master
而(将运行数亿次)
{
用于(在5到20次迭代之间)
{
#pragma-omp任务
(某物)
}

#pragma omp taskwait对于并行编程,您还应该以很少需要同步线程的方式设计问题。每次同步线程时,您将获得所有线程中最差的性能。如果需要同步线程,请尝试重新设计问题,以避免这些同步

将代码从
#pragma omp parallel for
调整为
#pragma omp task
不会带来任何显著的改进,因为它们的执行时间差通常是可以忽略的。在尝试调整一些例程调用或omp语句之前,您需要将问题调整为并行执行。您需要真正考虑“并行”为了获得良好且可扩展的性能提升,仅仅调整串行代码很少奏效


在您的代码中,您应该尝试并行化while循环,而不是内部for循环。如果并行化小for循环,则不会获得任何显著的性能提高。

我不确定任务是否正确。我不太熟悉任务,但似乎每次遇到
\pragma om时都会启动一个线程p任务
。我宁愿尝试以下方法:

while (will be run some hundreds of millions of time)
{
#pragma omp parallel
{
    for (between 5 and 20 iterations)
    {
        (something) 
    }
#pragma omp single/master
{

    (something)
    bool flag = false;
    if (something)
    {
        (something)
        flag = true;
    }
}

    if (flag)
    {
        for (between 50 and 200 iterations)
        {
            (something)
        }
    }
#pragma omp single/master
{
            (something)
}
    }
    }

同样重要的是要记住,for循环中的任务对于并行执行来说可能太小,以提供任何加速,因为在启动和同步线程时会有开销。您还应该考虑重写程序的可能性,这样您就不需要同步线程,而您现在经常这样做。我猜是目前,您的算法和工作负载对于并行执行来说实际上太小了,无法像现在编写的那样提高速度。

您是否记得相应地设置您的环境变量?OMP_NUM_THREADS=N,其中N是处理器支持的线程或核心数,恐怕这是完全不可能的。我意识到在上面的例子中并不明显,但是while循环中的每个迭代都依赖于前面的迭代,因此它们必须按顺序进行。然后尝试重新设计您的问题,以获得独立的循环。否则,您将浪费时间调整并行执行得不好的代码。这将使每个迭代进行n次(n是线程数),因此实际上没有任何好处。使用任务不会启动新线程,而是使用当前团队的线程,这些线程当前处于搁置状态(不完全正确,但足够接近)for循环的每次迭代需要多长时间?如果任务太小,很可能根本不可能在这里获得加速。此外,为什么
#pragma omp task
#pragma omp for
更快?毕竟后者应该能够以更少的管理开销获得成功。在我看来,如果t更快您可能在您的情况下使用了错误的调度模式。关于任务等待:据我所知,
master
部分应该是您的父任务(或者可能是
parallel
部分,但这似乎不太可能)我认为任务会更快,因为对一个老问题的回答大致是这样的:“如果for循环中的迭代次数太少,那么最好改用任务”。在串行情况下,可以在1.7秒内完成10000次while循环迭代。考虑到其他设置,第二次for循环的每次迭代的大致估计值为1.0-0.5微秒。我知道这很短,但有人告诉我低估了并行化的能力,并决定试一试:)听起来你真的需要考虑一种新的算法,或者一种新的并行处理范式,或者两者兼而有之。如果迭代的执行时间相差很大,任务在几次迭代中可能更快的原因是更好的负载平衡。但是,你也应该能够使用动态调度获得这种效果。1.0µs/任务对并行化产生积极影响来说似乎有点低。我预计任务的开销大约在几千个时钟的范围内,大约一微秒。毕竟原子学,把东西移动到不同的缓存中,这些东西并没有那么便宜。@talonmies一个不同的并行处理范例,那会是什么?我没有尝试过他根本没有考虑环境变量,但让“#pragma omp parallel”自己来解决。我的各种版本的“hello world”显示了正确的输出数(2)。你是什么意思?上面的内容?是的,如果我不提供“-fopenmp”对于g++,代码将以串行方式运行。这就是为什么我可以说并行版本太慢的原因。我是否正确理解了您的问题?对不起,我的意思是问您是否对其进行了分析。从情况看,这听起来像是您的处理器不太可能运行,或者您的代码存在某些竞争条件或同步问题这使得openMP速度变慢