在具有例程调用的并行区域中使用 PGI 而不是 Cray 进行编译时出现运行时错误

Runtime error when compiling with PGI instead of Cray in a parallel region with a routine call

我有一个问题:当我用 PGI 而不是 Cray 编译时,我的代码确实给了我一个运行时错误。代码进入并行区域时失败并给我一个分段错误。

我尝试了几件事,发现将标量(var4,参见代码)传递给子例程工作正常。但是将数组(var3,参见代码)传递给例程失败。

该代码使用 Cray 编译时没有任何问题,但使用 PGI 时却出现问题。

所以,我的问题是:PGI 和 Cray 在设备上分配数组的方式有区别吗?

调用的并行区域如下所示:

     !$acc data present(var2,var3,var4)
     !$acc parallel
       !$acc loop gang vector collapse(2) private(var1)
       DO j = 1, jend
         DO i = 1, iend
           IF (var2(i,j) .gt. 100.0) THEN
             CALL routine_seq ( var3(i,j,:),  &
                                var4(i,j),    &
                                var1)
           END IF
         END DO
       END DO
       !$acc end parallel

在例程中我包含了 !$acc 例程 seq。看起来像这样:

   SUBROUTINE routine_seq(var3,var4)
    !$acc routine seq
    REAL (KIND=wp), DIMENSION( : ),             &
         INTENT( IN ) ::                               var3

    REAL (KIND=wp), DIMENSION( : ),             &
         INTENT(  IN ) ::                               var4

    REAL (KIND=wp),                             &
         INTENT( OUT ) ::                               var1

var3 和 var4 是这样分配的:

    ALLOCATE ( var3(iend,jend,kend) , STAT=ierr); IF (ierr/=0) istat=ierr
    ALLOCATE ( var4(iend,jend) , STAT=ierr); IF (ierr/=0) istat=ierr
    !$acc enter data create(var3,var4)

由于错误是段错误,这意味着问题出在主机端。

尝试为您添加一个 "present" 子句 "parallel" 地区:

!$acc parallel present(var2,var3)

虽然由于您没有提供完整的重现示例而有点难以确定,但我对问题的最佳猜测是编译器无法正确确定隐式副本需要多少数组进入该区域,因为 var3 不在该区域中使用,除非作为调用的参数。 PGI 将尝试仅隐式复制最少量的数组。添加 "present" 将禁用隐式复制,如果数组已经在设备上存在设备副本,则让它只检查当前的 table。或者,您可以将 "copy(var2,var3)" 用于 "present_or_copy" 语义,其中当前检查将针对整个数组而不是子集。

要查看编译器使用什么进行隐式复制,请尝试添加“-Minfo=accel”以启用编译器反馈消息。