2015-09-29 181 views
0

我想在我的程序中並行化一個循環,所以我搜索了多線程。首先我看看POSIX多線程編程教程,它非常複雜,所以我試圖做一些簡單的事情。我嘗試使用OpenMP。我已經成功地並行化了我的代碼,但執行時間問題比系列案例更差。這是低於一部分確定我的程序。我希望你告訴我有什麼問題。我應該指定哪些變量是共享的,什麼是私有的?我怎麼知道每個變量的種類?我希望你能回答我,因爲我在很多論壇上搜索過,但我仍然不知道該怎麼做。OpenMP低性能

#include <stdio.h> 
#include <math.h> 
#include <stdlib.h> 
#include <time.h> 
#include <omp.h> 
#define D    0.215   // magnetic dipolar constant 

main() 
{ 
    int  i,j,n,p,NTOT = 1600,Nc = NTOT-1; 
    float r[2],spin[2*NTOT],w[2],d; 
    double E,F,V,G,dU; 
    . 
    . 
    . 
    for(n = 1; n <= Nc; n++){ 
    fscanf(voisins,"%d%d%f%f%f",&i,&j,&r[0],&r[1],&d); 
    V = 0.0;E = 0.0;F = 0.0; 
    #pragma omp parallel num_threads(4) 
    { 
     #pragma omp for schedule(auto) 
     for(p = 0;p < 2;p++) 
     { 
     V += (D/pow(d,3.0))*(spin[2*i-2+p]-w[p])*spin[2*j-2+p]; 
     E += (spin[2*i-2+p]-w[p])*r[p]; 
     F += spin[2*j-2+p]*r[p]; 
     } 
    } 
    G = -3*(D/pow(d,5.0))*E*F; 
    dU += (V+G); 
    } 
    . 
    . 
    . 
}//End of main() 
+1

*的問題執行時間比串行情況更差*這通常是使用錯誤的時序例程的結果。你的代碼沒有顯示你正在使用的是什麼,最好確定它是'omp_get_wtime'。 –

回答

2

您並行化循環,只有2次迭代:p=0p=1。 OpenMP的omp for的工作方式是在並行團隊(您定義爲4個線程)中的線程之間拆分循環迭代,並讓它們並行處理其問題的一部分。

只有2次迭代,2個線程將閒置。最重要的是,實際確定哪些線程可以解決問題的哪一部分需要開銷。如果您的實際循環不需要很長時間(在這種情況下顯然不會),那麼開銷將比並行化帶來的好處更多。

更好的策略通常是儘可能地將最外層的循環與OpenMP並行化,以解決均勻分割工作和減少(相對)開銷的問題。或者,您可以使用OpenMP 4.0的omp simd命令在最低循環級別進行並行化。

最後,您沒有正確計算變量VEF。因爲它們是從迭代到迭代的總和,所以應該用reduction(+:V)將它們全部定義爲約簡變量。如果你現在正在得到正確答案,我會感到驚訝。

(亦作高性能Mark說:。確保你定時程序的掛鐘時間執行,而不是你的程序的CPU時間執行這通常與omp_get_wtime()完成)

+0

謝謝你鼻子給你回答我認爲這是有幫助的。我並行化了外部循環,但在這種情況下,CPU的頂部活動顯示45%專用於我們,15%用於sy,40%用於id,當我平行化內部循環時不是這種情況(99%用於我們)。我確實理解你對這兩條空閒線程所說的話,但時間問題仍然存在。你認爲我應該說哪些變量是共享的,哪些是私人的,以避免競爭條件? –

+0

OpenMP的默認值是每個變量都是共享的。在這種情況下,當並行化內部循環時,只需要指定'V','E'和'F'是還原變量,'p'是私有的。 – NoseKnowsAll

+0

並行化你的外部循環(我相信這是一條可行的路線)將需要'#pragma omp parallel for private(n,V,E,F,p,G)還原(+:dU)num_threads(4)' – NoseKnowsAll