2013-11-21 121 views
6

我目前正在使用OpenMP進行矩陣計算。我在我的代碼中有幾個循環,而是調用每個循環#pragma omp parallel for [...](創建所有線程並在之後立即銷燬它們),我想在開始時創建它們,並且在程序結束時刪除它們以避免開銷。 我想是這樣的:如何使用OpenMP在並行循環中嵌套並行循環

#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 

它不能編譯,我得到這個錯誤來自海灣合作委員會:「工作共享區域不可以緊密嵌套在工作共享,臨界,有序,主要的或顯式的任務區域內」。

我知道它一定來自於「錯誤」的嵌套,但我不明白爲什麼這是行不通的。我需要在並行區域之前添加屏障嗎?我有點失落,不知道如何解決它。

非常感謝您的幫助。 乾杯。

回答

3

在過去的代碼的概述聲明並行區域,裏面使用的主指令,以確保只有主線程執行塊,和主塊試圖parallelise所有線程在一個循環中。你聲稱知道編譯錯誤是由不正確的嵌套造成的,但是奇怪爲什麼它不起作用。

它不起作用,因爲的代碼只有一個線程將執行沒有任何意義的區域內分配工作到多線程。

你的第一個僞代碼是好,但你可能要像這樣延伸:

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

    #pragma omp single 
    { ... } 

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

single指令確保代碼是封閉塊只能由一個線程執行。不同於master指令single也意味着出口處的障礙;您可以使用nowait子句更改此行爲。

+0

謝謝你的回答。我將嘗試重新排列我的代碼,以使結構更簡單並行。 – user3014051

3

OpenMP的大部分運行時間不「創建的所有線程和右後消滅他們」。線程在第一個OpenMP部分的開始處創建,並在程序終止時銷燬(至少英特爾的OpenMP實現如此)。使用一個大平行區域而不是幾個小平行區域沒有性能優勢。

英特爾的運行時(這是開源的,可以發現here)的選項來控制,當他們用完工作線程怎樣做。默認情況下,他們會旋轉一段時間(如果程序立即啓動一個新的平行部分),然後他們會自己睡覺。如果確實睡眠了,那麼爲下一個並行部分啓動它需要更長的時間,但這取決於區域之間的時間,而不是語法。