更好地使用openmp

Using openmp better

本文关键字:openmp 更好      更新时间:2023-10-16

我正在尝试实现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)
    }
}
}

只有两个for循环可以并行化,其余的必须按照正确的顺序进行。我提出将并行指令和主指令放在while循环之外,试图减少创建团队的开销。

我也有点好奇我是否正确地使用了taskwait——规范规定"父任务"将被搁置,直到所有子任务都被执行完毕,但不太清楚这个术语是否也适用于这里,因为这里没有嵌套任务区域。

有人能想出一个更好的方法来使用openMP吗?这样我就可以加速了?

EDIT:while循环中的每个步骤都依赖于之前的所有步骤,因此它们必须串行完成,并在最后进行更新。如果有人想知道的话,这是一种用于模拟神经网络的"事件驱动算法"的实现。

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

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

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

我不确定任务是否是正确的方法。我对任务不太熟悉,但似乎每次遇到#pragma omp task时,它都会启动一个线程。我宁愿试试类似的东西:

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是处理器支持的线程或内核数