我正在嘗試使用openmp任務來安排基本jacobi2d計算的平鋪執行。在jacobi2d存在來自在openmp中的依賴子句不尊重依賴聲明
上A(I,J)的依存A(I,J)
A(I-1,j)的
A(I + 1,J)
A(I, j-1)
A(i,j + 1)。
爲了我對depends子句的理解,我正確地聲明瞭依賴關係,但是在執行代碼時他們沒有被尊重。我已經複製下面的簡化代碼片段。最初我的猜測是某些圖塊的越界範圍可能會導致這個問題,所以我糾正了這個問題,但問題仍然存在(我沒有複製更長的代碼和更正後的圖塊範圍,因爲那部分只是一堆ifs +最大)
int n=8,tsteps=2,b=4; //n - size of matrix, tsteps - time iterations, b - tile size or block size
#pragma omp parallel
{
#pragma omp master
for (t=0; t<tsteps; ++t)
{
for (i=0; i<n; i+=b)
for (j=0; j<n; j+=b)
{
#pragma omp task firstprivate(t,i,j) depend(in:A[i-1:b+2][j-1:b+2]) depend(out:B[i:b][j:b])
{
#pragma omp critical
printf("t-%d i-%d j-%d --A",t,i,j); //Prints out time loop, i,j
}
}
for (i=0; i<n; i+=b)
for (j=0; j<n; j+=b)
{
#pragma omp task firstprivate(t,i,j) depend(in:B[i-1:b+2][j-1:b+2]) depend(out:A[i:b][j:b])
{
#pragma omp critical
printf("t-%d i-%d j-%d --B",t,i,j); //Prints out time loop, i,j
}
}
}
}
}
因此,與聲明的依賴關係與i-1和J-1的範圍內(b + 2)開始的想法是,相鄰區塊也影響當前的瓷磚計算。對於第二組循環,類似地,其中A的值只有在相鄰瓦片已經使用這些值時才被重寫。
正在使用支持openmp 4.0的gcc 5.3編譯代碼。
ps:上面聲明的數組範圍表示在創建相關圖時要考慮的起始位置和索引數。
編輯(基於Zulan的評論) - 將內部代碼更改爲簡單的打印語句,因爲這將足以檢查任務執行的順序。理想情況下,對於上述值(因爲只有4個圖塊),所有圖塊應該完成第一個printf,然後才執行第二個。但是如果你執行代碼,它會混合訂單。
爲什麼不在循環中使用工作共享?在第一個循環中,您從「B」讀取,但是寫入「A」。在第二個循環中,您寫入'A'並從'B'讀取。因此,第1部分先並行,然後第2部分並行。只要確保你同步part1和part2之間的線程(無論如何,除非你使用'nowait',否則應該是隱含的)。 –
當然,條件都是錯的? ( 「如果((ⅱ!= 0 || II!= N-1)||(JJ!= 0 || JJ!= N-1))」。考慮二== 0,仍然會由於0執行! = N-1,但你不希望它因爲它產生出界訪問... –
@Zboson - 是的,這是可以做到很好,它只是用任務給你一個稍微更有效地利用作爲理想小任務給你一個更高的並行性和更少的同步是必需的。 @吉姆。是的,你是對的,那就是與代碼中的錯誤,關鍵是依賴的問題仍然存在。我使用跟蹤依賴和執行順序在2內部ii和jj for循環之前單個打印,並且打印語句的順序不正確。我採取了預防措施,把這個印刷品放在重要的雜注裏,否則印刷品可能會非常不正確。 – hajmola