2014-10-30 105 views
0

當計算並行循環內的最大減少量循環執行期間中間時間最大減少變量的值是多少?它是僅針對特定線程的最大值還是它是所有線程的最大值?C++ openmp用於循環執行期間的循環最大減少值

我問的原因是我想使用循環內的當前最大值來執行計算,我希望它是所有線程的當前最大值,而不僅僅是執行循環的線程。

例如:

#include <stdio.h> 
#include <omp.h> 

int main(int argc, char *argv[]) { 

    double randomarray[10]; 
    //initialize the random array 

    double outputarray[10]; 
    double currentmax = 0; 

    #pragma omp parallel for reduction(max:currentmax) 
    for(i=0;i<10; i++) { 

     if(randomarray[i] > currentmax) 
     { 
      currentmax = randomarray[i]; 
     } 

     output[i]=randomarray[i]/currentmax; 
     // is this current max for the currently 
     // executing thread or all threads? 
    } 

} 
+0

您當前密碼過於簡單,內存帶寬的限制。 – 2014-11-05 10:02:28

+0

@Zboson我有一個具體的問題,我試圖解決的地方,我需要知道目前的最大值之前已計算全局最大值;因此,您的兩次通過建議與我試圖解決的問題無關。如果你知道更好的解決方案,而不是「內存帶寬限制」,請分享。 – zimzam 2014-11-07 18:45:18

回答

1

它是僅針對特定線程的最大值還是它是所有線程的最大值?

這是OpenMP並行區域內的「每線程」私有值。

下面的代碼片段可能會實現你想要做的事情,但它並沒有那麼有意義。

#pragma omp parallel for 
for(i=0;i<10; i++) { 
    double local_max; 

    #pragma omp critical 
    { 
    if(randomarray[i] > currentmax) 
    { 
     currentmax = randomarray[i]; 
    } 
    local_max = currentmax; 
    } 

    output[i]=randomarray[i]/local_max; 
} 
2

還原變量的值在使用該reduction緊密和線程之間的不同之處構建體是未定義的。每個線程都有專用的變量副本。你將不得不重新考慮你的並行化。

從OpenMP的4規格:

對於並行和工作分享結構,每個列表 項目的私有副本創建,爲每個隱式任務,因爲如果私人條款 已被使用。 ...私人副本然後被初始化爲上面指定的 。在減少子句爲 指定的區域的末尾,通過使用指定縮減標識符的 組合器將原始列表項目的原始 值與每個私人副本的最終值組合起來進行更新。

0

其他響應明確表示openmp max reduction不提供我需要的功能。因此,我發現採用下文定義的原子max運算來實施它的另一種方式:

inline double __sync_fetch_and_max_double(double* address, double val) { 
    int64_t* address_as_int64 = (int64_t*)address; 
    int64_t old = *address_as_int64, assumed; 
    do { 
    assumed = old; 
    double assumed_double = *((double*)&assumed); 
    double min = (val > assumed_double) ? val : assumed_double; 
    old = __sync_val_compare_and_swap(address_as_int64, assumed, 
             *((int64_t*)&min)); 
    } while (assumed != old); 
    return *((double *)&old); 
} 

然後,從問題修改代碼來計算在所有線程之間共享的單個變量的最大值和存儲。由於函數是原子的,變量的值總是具有唯一值,這是所有線程的當前最大值。

修改後的代碼看起來是這樣的:

#include <stdio.h> 
#include <omp.h> 

int main(int argc, char *argv[]) { 

    double randomarray[10]; 
    //initialize the random array 

    double outputarray[10]; 
    double currentmax = 0; 

    #pragma omp parallel for 
    for(i=0;i<10; i++) { 

     __sync_fetch_and_max_double(&currentmax,randomarray[i]); 

     output[i]=randomarray[i]/currentmax; //max among all threads 

    } 

} 
+0

有很多不同的方法來做到這一點。例如。你不必使用原子或關鍵。你可以做第一遍以找到每個線程的最大值,然後將這些值傳遞給每個線程來糾正,然後再進行第二遍。這是我用前綴和做的。但是你現在做的是內存帶寬無論如何(前綴總和也是如此),所以它不是很有趣。你最終想要實現什麼? – 2014-11-05 09:59:45