繁体   English   中英

openmp订购关键部分

[英]openmp ordering critical sections

我正在尝试创建一个OpenMP程序,该程序将依次循环遍历。 我意识到线程不是用于顺序程序的-我正在尝试与单线程相比略有加速,或者至少使执行时间与单线程程序相似。

在我的#pragma omp并行部分中,每个线程都会计算自己的大型数组部分,并获取该部分的总和。 这些都可以并行运行。 然后,我希望线程按顺序运行,并将每个总和添加到TotalSum IN ORDER中。 因此线程1必须等待线程0完成,依此类推。 我在#pragma omp关键部分中包含此部分。 一切运行正常,除了仅线程0完成,然后程序退出。 如何确保其他线程继续轮询? 我已经尝试过sleep()和while循环,但是在线程0完成之后它继续退出。

我没有使用#pragma omp parallel,因为我需要跟踪每个线程访问的master数组的特定范围。 这是相关代码部分的简化版本:

//DONE and MasterArray are global arrays. DONE keeps track of all the threads that have completed

int Function()
{
    #pragma omp parallel
    {
    int ID = omp_get_thread_num
    variables: start,end,i,j,temp(array)  (all are initialized here)
    j = 0;

    for (i = start; i < end; i++)
    {
         if(i != start)
               temp[j] = MasterArray[i];
         else
               temp[j] = temp[j-1] + MasterArray[i];
         j++;
    }



    #pragma omp critical
    {     
        while(DONE[ID] == 0 && ERROR == 0) {

           int size = sizeof(temp) / sizeof(temp[0]);           

           if (ID == 0)  {
              Sum = temp[size];
              DONE[ID] = 1;
              if (some situation)
                 ERROR = 1;   //there's an error and we need to exit the function and program
           }
           else if (DONE[ID-1] == 1) {
              Sum = temp[size];
              DONE[ID] = 1;
              if (some situation)
                 ERROR = 1;   //there's an error and we need to exit the function and program
           }
        }
     }
     }
     if (ERROR == 1)
         return(-1);
     else
         return(0);
   }

初始化线程数后,从main调用此函数。 在我看来,并行部分完成了,然后我们检查错误。 如果发现错误,则循环终止。 我意识到这里有问题,但是我无法弄清楚是什么,现在我只是转圈而已。 任何帮助都会很棒。 再次,我的问题是该函数仅在线程0执行后退出,但未标记任何错误。 我也让它在pthreads中运行,但是执行起来更简单。 谢谢!

您尝试使用#pragma omp critical来订购线程是完全错误的。 任何时候关键部分中只能有一个线程,并且线程到达关键部分的顺序是不确定的。 因此,在您的代码中可能会发生以下情况:例如,线程#2首先进入关键部分,再也不会离开它,等待线程#1完成,而线程#1和其余线程在#pragma omp critical中等待。 而且,即使某些线程(例如线程#0)幸运地以正确的顺序完成了关键部分,它们也会在并行区域末尾的隐式屏障上等待。 换句话说,此代码几乎可以确保死锁。

我建议您对线程进行简单而自然的排序,即有序部分。 它看起来应该像这样:

#pragma omp parallel
{
    int ID = omp_get_thread_num();

    // Computations done by each thread

    #pragma omp for ordered schedule(static,1)
    for( int t=0; t<omp_get_num_threads(); ++t )
    {
        assert( t==ID );
        #pragma omp ordered
        {
            // Do the stuff you want to be in order
        }
    }
}

因此,您将创建一个并行循环,其迭代次数等于该区域中的线程数。 使用schedule(static,1)子句可以清楚地看到,每个线程按照线程ID的顺序分配一次迭代; ordered子句允许在循环内使用有序部分。 现在,在循环的主体中放置一个有序部分( #pragma omp ordered的块),它将以迭代的顺序执行,这也是线程ID的顺序(由断言确保)。

有关更多信息,您可以查看以下问题: omp有序子句如何工作?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM