使用英特尔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
答案 0 :(得分:1)
我们正在考虑这个(英特尔的编译器和OMP运行时团队),很快就会回复你。
同时,请注意,在您最内层的循环任务中,我认为您希望将“C”添加到共享列表中,因为那里有“默认(无)”。编译器应该警告过你(我注意到C ++编译器没有,Fortran没有,所以这是一个bug)。
修改后的答案:我们的编译器团队说子程序中的共享子句的使用存在错误 - 您在子程序中获得了对C的共享访问权限,但是在主程序中没有C2。
作为参考,TR6中的这个OpenMP规范说明: “注意 - 当相应的伪参数没有VALUE属性且其数据共享属性是按照规则中的实现定义时,将共享变量传递给过程可能导致使用临时存储来代替实际参数。第243页的第2.20.1.2节。这些条件有效地导致在过程引用期间引用和定义临时存储。此外,共享变量的值在过程引用之前被复制到中间临时存储中参数没有INTENT(OUT)属性,并且当伪参数没有INTENT(IN)属性时,将临时存储器退出到共享变量中。 (或其定义)任何其他任务与伪参数关联的共享存储必须与过程引用同步,以避免可能的竞争条件。“
尝试此操作:在返回之前将taskwait移动到DTRMM3子例程的末尾。达到此任务等待时,C仍将在范围内。
谢谢!
特里