Fortran 在具有例程调用的并行区域中使用PGI而不是Cray进行编译时出现运行时错误
我有一个问题:当我用PGI而不是Cray编译时,我的代码确实给了我一个运行时错误。当代码进入并行区域时失败,并给我一个分段错误 我尝试了几种方法,发现将标量(var4,请参阅代码)传递给子例程是正确的。但是将数组(var3,参见代码)传递给例程失败 使用Cray编译代码时没有任何问题,但使用PGI时会出现问题 因此,我的问题是:PGI和Cray在设备上分配阵列的方式是否有差异 调用的并行区域如下所示:Fortran 在具有例程调用的并行区域中使用PGI而不是Cray进行编译时出现运行时错误,fortran,openacc,pgi,Fortran,Openacc,Pgi,我有一个问题:当我用PGI而不是Cray编译时,我的代码确实给了我一个运行时错误。当代码进入并行区域时失败,并给我一个分段错误 我尝试了几种方法,发现将标量(var4,请参阅代码)传递给子例程是正确的。但是将数组(var3,参见代码)传递给例程失败 使用Cray编译代码时没有任何问题,但使用PGI时会出现问题 因此,我的问题是:PGI和Cray在设备上分配阵列的方式是否有差异 调用的并行区域如下所示: !$acc data present(var2,var3,var4) !$
!$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
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
在日常生活中,我有最好的选择$包括acc例行程序。看起来是这样的:
!$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
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)
由于错误是seg故障,这意味着问题出在主机端 尝试在“平行”区域添加“present”子句: 虽然由于没有提供完整的复制示例,所以有点难以确定,但我对这个问题的最佳猜测是,编译器无法正确确定隐式复制到区域中需要多少数组,因为var3除了作为调用的参数外,在该区域中没有使用。PGI将尝试仅隐式复制数组的最小数量。添加“present”将禁用隐式副本,而仅当阵列在设备上已经存在设备副本时,才让它检查present表。或者,您可以使用“copy(var2,var3)”作为“present_或_copy”语义,其中present检查将针对整个数组而不是子集
要查看编译器对隐式副本使用的内容,请尝试添加“-Minfo=accel”以启用编译器反馈消息。欢迎使用堆栈溢出。请拿着这本书学习。然后,给我们一个清晰的描述,你想做什么,你错了什么,你期望得到什么,以及一个简单的答案。在通话中使用:
var3(i,j:)
so3d,在分配中使用var3(iend,jend)
so2d。你没有收到编译警告/错误吗?是的,你是对的。我编辑了这个问题。使代码可读是一个错误。但我们至少需要看到声明、例程,但最好是一个显示问题的MWE。请尝试使用调试选项和边界检查进行编译,以查明问题所在。