我的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
时,程序将运行良好。有人可以告诉我为什么吗?
答案 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
上的常量。