[英]OpenMP Handmade reduction directive
我正在研究階乘函數。 我必須使用OpenMP編寫其並行版本。
double sequentialFactorial(const int N) {
double result = 1;
for(int i = 1; i <= N; i++) {
result *= i;
}
return result;
}
眾所周知,使用reduction tecnique可以有效地並行化該算法。
我知道存在reduction
條款( 標准 §§2.15.3.6)。
double parallelAutomaticFactorial(const int N) {
double result = 1;
#pragma omp parallel for reduction(*:result)
for (int i=1; i <= N; i++)
result *= i;
return result;
}
但是,我想嘗試實現還原tecnique“手工制作”。
double parallelHandmadeFactorial(const int N) {
// maximum number of threads
const int N_THREADS = omp_get_max_threads();
// table of partial results
double* partial = new double[N_THREADS];
for(int i = 0; i < N_THREADS; i++) {
partial[i] = 1;
}
// reduction tecnique
#pragma omp parallel for
for(int i = 1; i <= N; i++) {
int thread_index = omp_get_thread_num();
partial[thread_index] *= i;
}
// fold results
double result = 1;
for(int i = 0; i < N_THREADS; i++) {
result *= partial[i];
}
delete partial;
return result;
}
我希望最后兩個片段的性能非常相似,並且優於第一個片段。 但是,平均表現是:
Sequential Factorial 3500 ms
Parallel Handmade Factorial 6100 ms
Parallel Automatic Factorial 600 ms
我錯過了什么嗎?
感謝@Gilles和@PW,此代碼按預期工作
double parallelNoWaitFactorial(const int N) {
double result = 1;
#pragma omp parallel
{
double my_local_result = 1;
// removing nowait does not change the performance
#pragma omp for nowait
for(int i = 1; i <= N; i++)
my_local_result *= i;
#pragma omp atomic
result *= my_local_result;
}
return result;
}
如果數組元素恰好共享高速緩存行,則會導致錯誤共享 ,從而進一步導致性能下降。
為了避免這種情況
double partial
而不是double
數組partial
。 partial
結果來計算關鍵區域中的最終result
result
應該是一個不是並行區域私有的變量。 關鍵區域將如下所示:
#pragma omp critical
result *= partial;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.