考慮以下最小的C代碼示例。在編譯和執行export OMP_NUM_THREADS=4 && gcc -fopenmp minimal.c && ./a.out
(Debian 8上的GCC 4.9.2)時,這會在我的機器上生成5行rho=100
(有時也是200或400)。所有五條印刷線的預期輸出當然是rho=400
。爲什麼下面的OpenMP程序不能減少我的變量?
如果我在// MARKER
處插入更多代碼或在此處放置障礙物,程序更可能產生正確的結果。但即使有另一個障礙,它有時也會失敗,我的計劃也是如此。所以這個問題似乎是a
進入還原循環時未正確初始化。
OpenMP 4.0.0 manual甚至在第55頁的狀態在循環結構的末尾存在隱式屏障,除非指定了nowait子句。所以a
應該在這一點上設置。這裏出了什麼問題?我錯過了什麼嗎?
#include <stdio.h>
#ifdef _OPENMP
#include <omp.h>
#define ID omp_get_thread_num()
#else
#define ID 0
#endif
double a[100];
int main(int argc, char *argv[]) {
int i;
double rho;
#pragma omp parallel
{
#pragma omp for
for (i = 0; i < 100; i++) {
a[i] = 2;
}
// MARKER
rho = 0.0;
#pragma omp for reduction(+: rho)
for (i = 0; i < 100; i++) {
rho += ((a[i])*(a[i]));
}
fprintf(stderr, "[%d] rho=%f\n", ID, rho);
}
fprintf(stderr, "[%d] rho=%f\n", ID, rho);
return 0;
}
[鐺似乎產生正確的結果](http://melpon.org/ wandbox/permlink/Jmkv5VcXKQJ4sMNN) –
修改'rho'時你需要一個互斥嗎? – donjuedo
我不這麼認爲。手冊的第167頁說:* reduction條款指定了一個縮減標識符和一個或多個列表項。對於每個列表項,在每個隱式任務或SIMD通道中創建一個私有副本,並使用還原標識符的初始化程序值進行初始化。在區域結束後,使用與縮減標識符相關聯的組合器,使用私人副本的值更新原始列表項。* – valyron