在Fortran子例程

时间:2018-06-01 13:13:22

标签: arrays fortran subroutine

我的Fortran代码如下(test.f):

subroutine sub(n1,n2,wa)
implicit none
integer, intent(in)  :: n1, n2
real(4), intent(inout) :: wa(1_8:1_8*n1*n2)
integer(8) :: i, j, ms

print*, 'in sub, 1_8*n1*n2=', 1_8*n1*n2
print*, 'in sub, size of wa:', size(wa,kind=8)

ms=0
!$omp parallel default(shared) private(i,j,ms)
!$omp do 
    do i=1, n1
    do j=1, n2
       ms=(i-1)*n2+j
       wa(ms)=ms*1.d0
    enddo; enddo;
!$omp end do nowait
!$omp end parallel

print*, 'size of wa:', size(wa,kind=8)

return
end subroutine sub

program main
implicit none
integer, parameter :: n1=2**11,n2=2**20
real(4), allocatable :: wave(:)
integer :: ierr
integer(8) :: i

allocate(wave(1_8*n1*n2), stat=ierr)

!$omp parallel default(shared) private(i)
!$omp do
     do i=1_8,1_8*n1*n2
       wave(i)=0.d0
     enddo
!$omp end do nowait
!$omp end parallel


print*, 'in main, size of wave:', size(wave,kind=8)

call sub(n1, n2, wave)

print*, wave(1_8*n1*n2)

deallocate(wave, stat=ierr)
end program main

n1和n2可以更大,并确保n1 * n2是长整数(> 2 ** 31-1)。我只想测试如何在子程序中使用非常大的数组。

我编译:{{1​​}}。

如果我使用ifort -openmp -CB test.f选项来检查数组的绑定,子例程wa中的数组sub将会出错。

这是错误信息:

  

主要,波浪大小:2147483648
  in sub,1_8 * n1 * n2 = 2147483648
  在sub中,wa的大小:0
  forrtl:severe(408):fort:(2):阵列WA的下标#1有
  值108003329,大于-2147483648的上限。

错误信息中的数字是随机的。

当我在子程序中将-CB声明为wa时,程序将运行良好。有人可以告诉我为什么吗?

1 个答案:

答案 0 :(得分:0)

  

forrtl:severe(408):fort:(2):数组WA的下标#1有   值108003329,大于-2147483648的上限

错误的索引可能是随机的,但上限不是。 -2147483648是未经检查的表达式2**11 * 2**20的结果,对于默认的整数(kind = int32),因为最大可表示的数字是2**31-1 = 2147483647

您正在子例程中声明虚拟数组的上限,如下所示:

wa(1_8:1_8*n1*n2)

由于两个操作具有相同的优先级,可能编译器首先将n1和n2相乘,得到负结果,然后乘以1_8将其转换为更大的类型。我现在无法测试。

您可以尝试在表达式上使用括号,如果您有权访问调试器,则可以在运行时检查变量的类型和范围。

此外,不要依赖像4或8这样的“魔术类型”.Tosr数字取决于编译器。您应该使用selected_int_kind或内部模块iso_fortran_env上的常量。