C openmp排序关键部分

C openmp排序关键部分,c,multithreading,parallel-processing,openmp,C,Multithreading,Parallel Processing,Openmp,我正在尝试创建一个OpenMP程序,该程序将按顺序遍历循环。我意识到线程并不是为顺序程序设计的——我正在尝试与单个线程相比获得一点加速,或者至少保持与单个线程程序相似的执行时间 在我的#pragma omp parallel部分中,每个线程计算一个大数组中自己的部分,并获得该部分的总和。这些都可以并行运行。然后我希望线程按顺序运行,每个总和按顺序添加到TotalSum中。因此线程1必须等待线程0完成,以此类推。我把这部分放在一个#pragma omp临界区内。一切运行正常,只是只有线程0正在完成

我正在尝试创建一个OpenMP程序,该程序将按顺序遍历循环。我意识到线程并不是为顺序程序设计的——我正在尝试与单个线程相比获得一点加速,或者至少保持与单个线程程序相似的执行时间

在我的#pragma omp parallel部分中,每个线程计算一个大数组中自己的部分,并获得该部分的总和。这些都可以并行运行。然后我希望线程按顺序运行,每个总和按顺序添加到TotalSum中。因此线程1必须等待线程0完成,以此类推。我把这部分放在一个#pragma omp临界区内。一切运行正常,只是只有线程0正在完成,然后程序退出。如何确保其他线程将保持轮询?我尝试了sleep()和while循环,但它在线程0完成后继续退出

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

//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);
   }
//DONE和MasterArray是全局数组。“完成”跟踪已完成的所有线程
int函数()
{
#pragma-omp并行
{
int ID=omp\u get\u thread\u num
变量:start、end、i、j、temp(数组)(所有变量都在此处初始化)
j=0;
for(i=start;i
初始化线程数后,从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
        }
    }
}
#pragma omp并行
{
int ID=omp_get_thread_num();
//每个线程完成的计算
#订购计划的pragma omp(静态,1)

对于(int t=0;t感谢您的建议。我已经这样做了,现在它成功地完成了所有线程。我关心的是每个线程的本地变量。这些变量在每个线程进入临界区时默认为私有?还是需要在for循环中将它们声明为私有变量?我不确定但假设并行区域的局部变量和私有变量在该区域内的工作共享构造中保持私有(除非另有规定)。我试图在OpenMP规范中找到一些关于这方面的内容,但没有成功。为了安全起见,为循环声明这些变量为私有变量可能没有什么害处。