如何使用OpenMP在并行循环中嵌套并行循环

我目前正在使用OpenMP进行矩阵计算。 我在我的代码中有几个循环,而是调用每个循环#pragma omp parallel for [...](创建所有线程并在之后立即销毁它们),我想在开始时创建它们,并且在程序结束时删除它们以避免开销。 我想要这样的东西:

#pragma omp parallel
{
    #pragma omp for[...]
    for(...)

    #pragma omp for[...]
    for(...)
}

问题是我有一些只能由一个线程执行的部分,但是在一个包含必须并行执行的循环的循环中......这就是它的外观:

//have to be execute by only one thread
int a=0,b=0,c=0;
for(a ; a<5 ; a++)
{

    //some stuff

    //loops which have to be parallelize
    #pragma omp parallel for private(b,c) schedule(static) collapse(2)
    for (b=0 ; b<8 ; b++);
        for(c=0 ; c<10 ; c++)
        {
            //some other stuff
        }

    //end of the parallel zone
    //stuff to be execute by only one thread

}

(在我的例子中,循环边界非常小,在我的程序中迭代的次数可以达到20.000 ...)我的第一个想法是做这样的事情:

//have to be execute by only one thread
#pragma omp parallel    //creating all the threads at the beginning
{
    #pragma omp master //or single
    {        
        int a=0,b=0,c=0;
        for(a ; a<5 ; a++)
        {

            //some stuff

            //loops which have to be parallelize
            #pragma omp for private(b,c) schedule(static) collapse(2)
            for (b=0 ; b<8 ; b++);
                for(c=0 ; c<10 ; c++)
                {
                    //some other stuff
                }

            //end of the parallel zone
            //stuff to be execute by only one thread

        }
    }
} //deleting all the threads

它不会编译,我从gcc得到这个错误:“工作共享区域可能没有紧密嵌套在工作共享,关键,有序,主或明确的任务区域内”。

我知道它肯定来自“错误的”嵌套,但我不明白为什么它不起作用。 我需要在并行区域之前添加屏障吗? 我有点失落,不知道如何解决它。

预先感谢您的帮助。 干杯。


在最后一个代码大纲中,声明了一个并行区域,其中使用主指令来确保只有主线程执行一个块,并且主块内部试图跨所有线程并行循环。 你声称知道编译错误是由不正确的嵌套造成的,但是奇怪为什么它不起作用。

它不起作用,因为将工作分发给只有一个线程执行的代码区域内的多个线程是没有意义的。

你的第一个伪代码更好,但你可能想要这样扩展它:

#pragma omp parallel
{
    #pragma omp for[...]
    for(...)

    #pragma omp single
    { ... }

    #pragma omp for[...]
    for(...)
}

single指令确保它所包含的代码块仅由一个线程执行。 与master指令不同, single指也意味着退出时的障碍; 您可以使用nowait子句更改此行为。


大多数OpenMP运行时不会“创建所有线程并在之后立即销毁”。 线程在第一个OpenMP部分的开始处创建,并在程序终止时销毁(至少英特尔的OpenMP实现如此)。 使用一个大平行区域而不是几个小平行区域没有性能优势。

英特尔的运行时(这是开源的,可以在这里找到)有一些选项可以控制线程在不工作时执行什么操作。 默认情况下,他们会旋转一段时间(如果程序立即启动一个新的平行部分),然后他们会自己睡觉。 如果确实睡眠了,那么为下一个并行部分启动它需要更长的时间,但这取决于区域之间的时间,而不是语法。

链接地址: http://www.djcxy.com/p/79211.html

上一篇: How to nest parallel loops in a sequential loop with OpenMP

下一篇: Parallelize function using OpenMP