2016-08-05 96 views
2

我目前正在嘗試使用任務構建OpenMP 4.0,包括取決於聲明用於我的Fortran代碼。因此,我創建了下面的示例,它應該用一個任務填充1到M數字的矩陣的第一行,每當第一行的元素準備就緒時,每個任務填充剩餘的元素。這導致了下面的一段代碼:OpenMP - Fortran中的任務依賴關係

PROGRAM OMP_TEST 
    IMPLICIT NONE 

    INTEGER K,L 
    INTEGER M 
    PARAMETER (M = 8) 
    INTEGER A(M,M) 

    A(1:M, 1:M) = 0 

    !$omp parallel 
    !$omp single 
    DO L=1, M 
     !$omp task depend(out:A(1,L)) default(shared) 
     A(1,L) = L 
     !$omp end task 
     DO K = 2, M 
      !$omp task depend(in:A(1,L)) default(shared) 
      A(K,L) = A(1,L) 
      !$omp end task 
     END DO 
    END DO 
    !$omp taskwait 
    !$omp end single 
    !$omp end parallel 

    DO K =1 , M 
     WRITE(*,*) A(K,1:M) 
    END DO 
END PROGRAM 

編譯與英特爾Fortran編譯器15,這是根據文檔意識到的依賴聲明。但是,每次執行時,打印到屏幕的結果都不相同。即使矩陣的最初零點仍停留在某些位置。例如:

 1   2   3   4   5   6 
     7   8 
     0   0   0   0   0   0 
     0   0 
     0   0   3   4   0   0 
     0   8 
     1   0   3   4   0   6 
     0   8 
     1   0   3   4   5   6 
     0   8 
     1   2   3   4   5   6 
     7   8 
     0   2   3   4   5   6 
     7   0 
     1   2   3   4   5   6 
     0   8 

爲什麼任務之間的依賴關係不正確,因爲我希望它使得值1至8每一行中工作?

+0

使用gcc 5.4編譯會產生類似的錯誤結果。 –

回答

2

聲明

!$omp task depend(in:A(1,L)) default(shared) 
A(K,L) = A(1,L) 
!$omp end task 

認爲K爲共享,但在那個任務的執行時間的K價值可能已在其他地方修改(事實上,這可能只發生,因爲線程執行的單 - 它正在循環通過DO K = 2,M)。您可以通過將firstprivate子句添加到!$omp構造中來解決該問題。本條款確保K將是私有的,但是在創建該任務時也會繼承該值。

這個事實同樣適用於L這個同樣的陳述以及之前的一些行之前的任務。以下代碼適用於使用英特爾Fortran編譯器16.0版的我。

PROGRAM OMP_TEST 
    IMPLICIT NONE 

    INTEGER K,L 
    INTEGER M 
    PARAMETER (M = 8) 
    INTEGER A(M,M) 

    A(1:M, 1:M) = 0 

    !$omp parallel 
    !$omp single 
    DO L=1, M 
     !$omp task depend(out:A(1,L)) default(shared) firstprivate(L) 
     A(1,L) = L 
     !$omp end task 
     DO K = 2, M 
      !$omp task depend(in:A(1,L)) default(shared) firstprivate(K,L) 
      A(K,L) = A(1,L) 
      !$omp end task 
     END DO 
    END DO 
    !$omp taskwait 
    !$omp end single 
    !$omp end parallel 

    DO K =1 , M 
     WRITE(*,*) A(K,1:M) 
    END DO 
END PROGRAM 

更新

探索Grisu的評論,他/她指的是英特爾的例子後,我意識到,KL應該已經firstprivate,因爲他們是在DO循環變量。但是,添加default(shared)似乎改變了這種行爲。以下代碼已明確聲明共享變量並且default已被刪除,也適用於英特爾Fortran 16.0。

PROGRAM OMP_TEST 
    IMPLICIT NONE 

    INTEGER K,L 
    INTEGER M 
    PARAMETER (M = 8) 
    INTEGER A(M,M) 

    A(1:M, 1:M) = 0 

    !$omp parallel 
    !$omp single 
    DO L=1, M 
     !$omp task depend(out:A(1,L)) shared(A) 
     A(1,L) = L 
     !$omp end task 
     DO K = 2, M 
      !$omp task depend(in:A(1,L)) shared(A) 
      A(K,L) = A(1,L) 
     !$omp end task 
     END DO 
    END DO 
    !$omp taskwait 
    !$omp end single 
    !$omp end parallel 

    DO K =1 , M 
     WRITE(*,*) A(K,1:M) 
    END DO 
END PROGRAM 
+0

感謝這些作品,有趣的是英特爾網頁上的示例並不依賴firstprivate語句(https://software.intel.com/zh-cn/node/581281)以及其他許多示例。但通過這種方式,它可以工作,我可以繼續我的實驗。 –