子例程中OpenMP任务的分段错误(英特尔Fortran 2018 Update 1)

时间:2018-04-25 13:41:31

标签: segmentation-fault fortran openmp intel-fortran

使用英特尔Fortran 2018 Update 1编译器时遇到以下问题。我实现了一种块算法来计算一个不正常的三角矩阵 - 矩阵乘积C := alpha * A * B + beta *C,其中A是一个上三角矩阵。由于矩阵矩阵产品具有很大的并行化潜力,我使用OpenMP任务和任务依赖性来做到这一点。结束以下代码:

SUBROUTINE DTRMM3(M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
USE OMP_LIB
IMPLICIT NONE
DOUBLE PRECISION ALPHA,BETA
INTEGER LDA,LDB,LDC,M,N
DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
EXTERNAL DGEMM, DTRMM
INTRINSIC MAX
INTEGER K,KB,L,LB,J,JB
!     .. Parameters ..
DOUBLE PRECISION DONE,DZERO
PARAMETER (DONE=1.0D+0,DZERO=0.0D+0)
INTEGER NB
PARAMETER(NB=256)
!     .. Local Work...
DOUBLE PRECISION TMP(NB,NB)

IF (M.EQ.0 .OR. N.EQ.0) RETURN

IF (ALPHA.EQ.DZERO) THEN
    DO J = 1,N
        !$omp simd safelen(64)
        DO K = 1,M
            C(K,J) = BETA * C(K,J)
        END DO
        !$omp end simd
    END DO
    RETURN
END IF

DO L = 1,N,NB
    LB = MIN(NB,N - L + 1)
    DO K = 1,M,NB
        KB = MIN(NB, M - K + 1)
        !$omp task firstprivate(K,KB,L,LB) depend(inout: C(K:K+KB-1,L:L+LB-1)) shared(C,BETA)
        C(K:K+KB-1, L:L+LB-1) = BETA * C(K:K+KB-1,L:L+LB-1)
        !$omp end task
        DO J = K, M, NB
            JB = MIN(NB, M - J + 1)
            !$omp task firstprivate(K,KB,L,LB, J, JB) private(TMP) &
            !$omp& depend(in:A(K:K+KB-1,J:J+JB-1), B(J:J+JB+1,L:L+LB-1)) depend(inout: C(K:K+KB-1,L:L+LB-1)) &
            !$omp& shared(ALPHA,A,B,C,LDA,LDB,LDC) default(none)
            IF ( K .EQ. J ) THEN
                TMP(1:KB,1:LB) = B(K:K+KB-1,L:L+LB-1)
                CALL DTRMM("L","U","N","U", KB, LB, ALPHA, A(K,K), LDA, TMP, NB)
                C(K:K+KB-1, L:L+LB-1) = C(K:K+KB-1,L:L+LB-1) + TMP(1:KB,1:LB)
            ELSE
                CALL DGEMM("N", "N", KB, LB, JB, ALPHA, A(K,J), LDA, B(J,L), LDB, DONE, C(K,L),LDC)
            END IF
            !$omp end task
        END DO

    END DO
END DO
RETURN
END SUBROUTINE

并使用:

执行它
!$omp parallel
!$omp master
CALL DTRMM3(M, N, ALPHA, A, LDA, B, LDB, BETA, C2, LDC)
!$omp end master
!$omp taskwait
!$omp end parallel

可以找到整个示例here

我使用视图源

编译了代码
ifort -xHost -O3 dtrmm3_test.f90  -qopenmp -mkl -g

并在16核Xeon Silver 4110上执行它会导致分段错误:

./a.out
512   786     0.00000000D+00   0.00000000D+00   0.00000000D+00  T
512   786     0.00000000D+00   0.10000000D+01   0.00000000D+00  T
512   786     0.00000000D+00   0.20000000D+01   0.00000000D+00  T
forrtl: severe (174): SIGSEGV, segmentation fault occurred
forrtl: severe (174): SIGSEGV, segmentation fault occurred
forrtl: severe (174): SIGSEGV, segmentation fault occurred

前三行显示路径ALPHA = 0.0有效,只有在调用算法的基于任务的部分时才会崩溃。

Uisng GCC 7.3和Netlib BLAS一切正常,没有错误。

操作系统:CentOS 7.4,英特尔Fortran 2018 Update 1,MKL 2018 Update 1

1 个答案:

答案 0 :(得分:1)

我们正在考虑这个(英特尔的编译器和OMP运行时团队),很快就会回复你。

同时,请注意,在您最内层的循环任务中,我认为您希望将“C”添加到共享列表中,因为那里有“默认(无)”。编译器应该警告过你(我注意到C ++编译器没有,Fortran没有,所以这是一个bug)。

修改后的答案:我们的编译器团队说子程序中的共享子句的使用存在错误 - 您在子程序中获得了对C的共享访问权限,但是在主程序中没有C2。

作为参考,TR6中的这个OpenMP规范说明: “注意 - 当相应的伪参数没有VALUE属性且其数据共享属性是按照规则中的实现定义时,将共享变量传递给过程可能导致使用临时存储来代替实际参数。第243页的第2.20.1.2节。这些条件有效地导致在过程引用期间引用和定义临时存储。此外,共享变量的值在过程引用之前被复制到中间临时存储中参数没有INTENT(OUT)属性,并且当伪参数没有INTENT(IN)属性时,将临时存储器退出到共享变量中。 (或其定义)任何其他任务与伪参数关联的共享存储必须与过程引用同步,以避免可能的竞争条件。“

尝试此操作:在返回之前将taskwait移动到DTRMM3子例程的末尾。达到此任务等待时,C仍将在范围内。

谢谢!

特里