Использование большего массива в подпрограмме Fortran - PullRequest
0 голосов
/ 01 июня 2018

Мой код на Фортране ниже (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),Я просто хочу проверить, как использовать очень большой массив в подпрограмме.

Я компилирую с: ifort -openmp -CB test.f.

массив wa в подпрограмме sub выдаст ошибку, если я использую опцию -CB для проверки границы массива.

Это информация об ошибке:

в основном, размер волны: 2147483648
в sub, 1_8 * n1 * n2 = 2147483648
в sub, размер wa: 0
forrtl: суровое (408): fort: (2): индекс # 1 массива WA имеет значение
108003329, которое превышает верхнюю границу -2147483648.

число в информации об ошибке является случайным.

Когда я объявляю wa в подпрограмме как real(4), intent(inout) :: wa(1), программа будет работать хорошо.Может кто-нибудь сказать мне, почему?

1 Ответ

0 голосов
/ 01 июня 2018

forrtl: суровый (408): форт: (2): индекс # 1 массива WA имеет значение 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. Числа Thosr зависят от компилятора.Вы должны использовать selected_int_kind или константы встроенного модуля iso_fortran_env.

...