我試着編寫一個C(gcc)函數,它將在多線程中運行時計算雙精度數組的最大值。我創建了一個大小爲omp_get_num_threads
的數組,其中我存儲了每個線程的局部最大值,然後才最終使這個小數組最大化。該代碼是(或多或少)以下:Openmp沒有更新
int i;
double *local_max;
double A[1e10]; //made up size
#pragma omp parallel
{
#pragma omp master
{
local_max=(double *)calloc(omp_get_num_threads(),sizeof(double));
}
#pragma omp flush //so that all threads point
//to the correct location of local_max
#pragma omp for
for(i=0;i<1e10;i++){
if(A[i]>local_max[omp_get_thread_num()])
local_max[omp_get_thread_num()]=A[i];
}
}
free(local_max);
然而,這會導致段錯誤,並且未初始化變量的使用Valgrind的的抱怨。事實證明,在輸入for
構造之前,local_max實際上並未在所有線程中更新。我認爲#pragma omp flush
應該這樣做?如果我用#pragma omp barrier
代替它,一切正常。
有人可以向我解釋發生了什麼事嗎?
非常感謝你,這很有道理。我遇到的一個後續問題是,當線程遇到'flush'構造時,是否所有線程同時進行同步?他們在哪裏恢復執行? – Ivan 2013-02-16 00:44:30
'flush'是一個棘手的問題,並且傾向於讓我們認爲所有的線程都會停止並同步,然後所有的線程都會繼續愉快地執行。但這是錯誤的。當線程遇到'flush'時,它會同步並恢復執行。您可以使用omp_get_wtime來打印執行時間,並在代碼中添加一些隨機睡眠呼叫,以查看其執行方式。我建議你避免使用'flush',因爲它增加了相當高的複雜性。 – ikikenis 2013-02-16 01:06:58
這是否意味着其他線程不會與遇到'flush'的同時同步?他們在訪問一個變量的過程中是什麼,但在並行構造的不同部分呢? – Ivan 2013-02-16 01:20:30