2016-08-05 15 views
2

現在、タスクのOpenMP 4.0の構成を使用しようとしています。これは、に依存しています。したがって、次の例を作成します。この例では、タスクによって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〜8は、それぞれの行にあることを期待するよう

 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 

はなぜタスク間の依存関係が正しく動作しませんん:たとえば?

+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さんのコメントを探索した後、私は彼らがDOのループ変数であるため、KLはすでにfirstprivateでなければならないことに気づきました。しかし、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

興味深いことに、興味深いことにインテルWebページの例は、firstprivateステートメント(https://software.intel.com/en-us/node/581281)や他の多くの例に依存していません。しかし、このようにして動作し、私は実験を続けることができます。 –

関連する問題