简体   繁体   English

openmp订购关键部分

[英]openmp ordering critical sections

I am trying to create an OpenMP program that will sequentially iterate through a loop. 我正在尝试创建一个OpenMP程序,该程序将依次循环遍历。 I realize threads are not intended for sequential programs -- I'm trying to either get a little speedup compared to a single thread, or at least keep the execution time similar to a single-threaded program. 我意识到线程不是用于顺序程序的-我正在尝试与单线程相比略有加速,或者至少使执行时间与单线程程序相似。

Inside my #pragma omp parallel section, each thread computes its own section of a large array and gets the sum of that portion. 在我的#pragma omp并行部分中,每个线程都会计算自己的大型数组部分,并获取该部分的总和。 These all may run in parallel. 这些都可以并行运行。 Then I want the threads to run in order, and each sum is added to the TotalSum IN ORDER. 然后,我希望线程按顺序运行,并将每个总和添加到TotalSum IN ORDER中。 So thread 1 has to wait for thread 0 to complete, and so on. 因此线程1必须等待线程0完成,依此类推。 I have this part inside a #pragma omp critical section. 我在#pragma omp关键部分中包含此部分。 Everything runs fine, except that only thread 0 is completing and then the program exits. 一切运行正常,除了仅线程0完成,然后程序退出。 How can I ensure that the other threads will keep polling? 如何确保其他线程继续轮询? I've tried sleep() and while loops, but it continues to exit after thread 0 completes. 我已经尝试过sleep()和while循环,但是在线程0完成之后它继续退出。

I am not using #pragma omp parallel for because I need to keep track of the specific ranges of the master array that each thread accesses. 我没有使用#pragma omp parallel,因为我需要跟踪每个线程访问的master数组的特定范围。 Here is a shortened version of the code section in question: 这是相关代码部分的简化版本:

//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);
   }

this function is called from main after initializing the number of threads. 初始化线程数后,从main调用此函数。 It seems to me that the parallel portion completes, then we check for an error. 在我看来,并行部分完成了,然后我们检查错误。 If an error is found, the loop terminates. 如果发现错误,则循环终止。 I realize something is wrong here, but I can't figure out what it is, and now I'm just going in circles. 我意识到这里有问题,但是我无法弄清楚是什么,现在我只是转圈而已。 Any help would be great. 任何帮助都会很棒。 Again, my problem is that the function exits after only thread 0 executes, but no error has been flagged. 再次,我的问题是该函数仅在线程0执行后退出,但未标记任何错误。 I have it running in pthreads too, but that has been simpler to execute. 我也让它在pthreads中运行,但是执行起来更简单。 Thanks! 谢谢!

Your attempt of ordering threads with #pragma omp critical is totally incorrect. 您尝试使用#pragma omp critical来订购线程是完全错误的。 There can be just one thread in a critical section at any time, and the order in which the threads arrive to the critical section is not determined. 任何时候关键部分中只能有一个线程,并且线程到达关键部分的顺序是不确定的。 So in your code it can happen that eg the thread #2 enters the critical section first and never leaves it, waiting for thread #1 to complete, while the thread #1 and the rest are waiting at #pragma omp critical . 因此,在您的代码中可能会发生以下情况:例如,线程#2首先进入关键部分,再也不会离开它,等待线程#1完成,而线程#1和其余线程在#pragma omp critical中等待。 And even if some threads, eg thread #0, are lucky to complete the critical section in right order, they will wait on an implicit barrier at the end of the parallel region. 而且,即使某些线程(例如线程#0)幸运地以正确的顺序完成了关键部分,它们也会在并行区域末尾的隐式屏障上等待。 In other words, the deadlock is almost guaranteed in this code. 换句话说,此代码几乎可以确保死锁。

I suggest you do something much simpler and natural to order your threads, namely an ordered section. 我建议您对线程进行简单而自然的排序,即有序部分。 It should look like this: 它看起来应该像这样:

#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
        }
    }
}

So you create a parallel loop with the number of iterations equal to the number of threads in the region. 因此,您将创建一个并行循环,其迭代次数等于该区域中的线程数。 The schedule(static,1) clause makes it explicit that the iterations are assigned one per thread in the order of thread IDs; 使用schedule(static,1)子句可以清楚地看到,每个线程按照线程ID的顺序分配一次迭代; and the ordered clause allows to use ordered sections inside the loop. ordered子句允许在循环内使用有序部分。 Now in the body of the loop you put an ordered section (the block following #pragma omp ordered ), and it will be executed in the order of iterations, which is also the order of thread IDs (as ensured by the assertion). 现在,在循环的主体中放置一个有序部分( #pragma omp ordered的块),它将以迭代的顺序执行,这也是线程ID的顺序(由断言确保)。

For more information, you may look at this question: How does the omp ordered clause work? 有关更多信息,您可以查看以下问题: omp有序子句如何工作?

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

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