2016-08-05 98 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)以及其他许多示例。但通过这种方式,它可以工作,我可以继续我的实验。 –