OpenMP - Fortran中的任务依赖

时间:2016-08-05 06:46:44

标签: parallel-processing fortran openmp

我目前正在尝试使用OpenMP 4.0的任务结构,包括我的Fortran代码的 depend 语句。因此,我创建了以下示例,该示例应该通过任务填充数字1到M的矩阵的第一行,并且每当第一行中的元素准备就绪时,通过任务填充剩余的元素。这导致以下代码:

use JSON;

my $result = from_json($json);
if($result->{field})
{
  # YOUR CODE
};

使用英特尔Fortran 15编译器进行编译,该编译器根据 depend 语句的文档知识。但是每次执行时打印到屏幕上的结果都不同。即使矩阵的初始零点也停留在某些位置。例如:

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 

为什么任务之间的依赖关系不能正常工作,因为我希望每行中的值为1到8?

1 个答案:

答案 0 :(得分: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