簡體   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