2012-06-28 58 views
6

對於OpenMP 3.1,有可能有一個reduction子句min查找在陣列的最小元素,它的索引

double m; 
#pragma omp parallel for reduction(min:m) 
for (int i=0;i< n; i++){ 
    if (a[i]*2 < m) { 
    m = a[i] * 2; 
} 
return m; 

假設我還需要的最小元件的索引;有沒有辦法使用這個reduction條款?我相信替代方法是使用nowaitcritical手動編寫縮減。

回答

5

假設我也需要最小元素的索引;有沒有辦法使用這個減少子句?

不幸的是,沒有。 OpenMP可能的減少列表非常小。特別是,minmax是唯一的「高級」功能,它們不是可定製的。完全一樣。

我不得不承認,我不喜歡OpenMP的減少方法,正因爲它不能在一定程度上擴展,所以設計的只適用於特殊情況。當然,這些是有趣的特殊情況,但它仍然是一個根本不好的方法。

對於這樣的操作,您需要通過將線程局部結果累加到線程局部變量並在末尾組合它們來實現自動縮減。

這樣做的最簡單的方法(實際上與OpenMP實現的減少方法非常接近)是爲每個線程使用一個包含元素的數組,並使用omp_get_thread_num()來訪問元素。但請注意,如果陣列中的元素共享緩存行,則會導致性能下降,原因是虛假共享。爲了緩解這一點,墊陣列:

struct min_element_t { 
    double min_val; 
    size_t min_index; 
}; 

size_t const CACHE_LINE_SIZE = 1024; // for example. 
std::vector<min_element_t> mins(threadnum * CACHE_LINE_SIZE); 

#pragma omp parallel for 
for (int i = 0; i < n; ++i) { 
    size_t const index = omp_get_thread_num() * CACHE_LINE_SIZE; 
    // operate on mins[index] … 
} 
+0

我想你的意思是'omp_get_num_threads'? – user1071136

+0

@ user1071136不,我的意思是'omp_get_thread_num'。我們希望*索引*,而不是總數。至於'threadnum',這是一個佔位符。您不能在這裏使用'omp_get_num_threads',因爲您不在並行區域內。相反,實際上應該將'numthread'作爲後續parallel子句中的線程數。 –

+0

提及虛假分享。儘管如此,OpenMP減少子句是爲了高效和易於實現而設計的,而不是爲了可擴展性。 –