2013-08-06 23 views
0

我學習OpenMP的,現在,我有一個問題。儘管所有線程都訪問該函數,但以下代碼的工作時間和沒有並行部分的相同代碼在統計上是相等的。我試圖看看互聯網上的一些指南,但它沒有幫助。所以問題是,這個平行部分有什麼問題?打開熔點爲平行不工作

int sumArrayParallel() 
{ 

    int i = 0; 
    int sum = 0; 
    #pragma omp parallel for 
    for (i = 0; i < arraySize; ++i) 
    { 
     cout << omp_get_thread_num() << " "; 
     sum += testArray[i]; 
    } 
    return sum; 
} 

回答

4

還有的OpenMP的代碼沒有對他們的串口對應表現出改善的性能兩個非常常見的原因:

  1. 正在做的工作是不足以超過並行計算的開銷。想想有一段時間,建立一個線程團隊,分配工作給他們,從他們那裏收集結果的成本。除非這個成本低於並行化計算所節省的時間,否則OpenMP代碼即使正確,也不會顯示任何加速並可能顯示相反的結果。你沒有向我們顯示數字,所以你自己的計算。

  2. 程序員強加給並行程序串行操作,或者通過包裝的內部存儲器圍欄的數據訪問,可能通過訪問平臺資源,這是固有的串行。我懷疑(但我對C的知識很糟糕),你對cout的寫作可能會無意中使你的計算部分串行化。

當然,你可以混合使用這兩個問題,太多的序列化和沒有足夠的工作,導致性能令人失望。

進一步的閱讀this page on Intel's website是有用的,而不是隻爲初學者。

我認爲,雖然,你有你的代碼比它差的並行性能更嚴重的問題。 OpenMP版本是否產生正確的sum?既然你沒有做出具體規定sum被所有線程共享,他們將比賽訪問它。在學習OpenMP的同時,將條款default(none)附加到並行區域並負責定義每個區域中每個變量的共享/私有狀態是一個非常好的主意。然後,一旦你流利地使用OpenMP,你就會知道爲什麼繼續使用default(none)條款是有意義的。

即使您回覆是的,代碼確實會產生正確的結果數據競爭存在,您的程序不能被信任。數據競賽非常有趣,它們並沒有出現在你運行的所有測試中,一旦你將代碼推廣到生產中,轟炸!和蛋全在你的臉上。

但是,你似乎是滾動自己reduction和OpenMP提供的工具這樣做。調查OpenMP引用中的reduction子句。如果我正確地讀你的代碼,並考慮到以上的建議,你可以重寫環路

#pragma omp parallel for default(none) shared(sum, arraySize, testArray) private(i) reduction(+:sum) 
for (i = 0; i < arraySize; ++i) 
{ 
    sum += testArray[i]; 
} 

簡而言之,使用還原子句告訴OpenMP的梳理總結,從工作單個值的問題跨線程分佈,避免競爭條件

由於OpenMP使循環迭代變量默認爲私有,因此您可以從指令中省略子句private(i),而沒有太多風險。更妙的是,雖然可能會宣佈它裏面的語句:並行區域內聲明的(撇開一些特殊情況下)總是私人

#pragma omp parallel for default(none) shared(sum, arraySize, testArray) reduction(+:sum) 
for (int i = 0; i < arraySize; ++i) 

變量。