Неоднократно используемый 2D-массив в подпрограмме Fortran 90 - PullRequest
1 голос
/ 12 июля 2020

У меня есть программа на Фортране 90, структура которой показана ниже. Шаг compute the 2D array myMatrix(1:N,1:N) в subroutinne A стоит дорого. Он зависит только от глобальной переменной N, и его нужно вычислить только один раз; «другие шаги» подпрограммы не изменят значение myMatrix. В настоящее время myMatrix будет вычисляться всякий раз при вызове подпрограммы.

Есть ли способ написать программу таким образом, чтобы 2D-массив myMatrix вычислялся только один раз?

module constants
    integer :: N
end module constans

module A_module
use constants
contains
    subroutine A
    ! compute the 2D real array myMatrix(1:N,1:N)
    ! other steps that use myMatrix
    end subroutine A
end module A_module

program main
    use constants
    use A_module
    integer :: k

    do  k = 1,10000
        call A 
    end do

end program main

Ответы [ 2 ]

1 голос
/ 12 июля 2020

Если myMatrix - это несохраненная , локальная переменная подпрограммы A, то необходимо будет пересчитывать ее значения для каждой записи подпрограммы: несохраненная локальная переменные становятся неопределенными, когда подпрограмма завершает выполнение.

Однако есть несколько подходов к повторному использованию переменной:

  • сделать ее сохраненной локальной переменной: сохраненные локальные переменные сохраняют свое определение
  • имеют его как фиктивный аргумент, а не локальную переменную (ассоциация аргументов): его определение исходит от вызывающего
  • имеет его как некоторую другую форму нелокальной переменная (другие формы ассоциации ): ее определение происходит из другого места

Если это сохраненная переменная, вычислить ее при первой записи подпрограммы и сохранить ее определение при последующих вызывает:

subroutine A
  <declaration>, save :: mymatrix
  logical, save :: first_entry = .TRUE.

  if (first_entry) then
     ! set up mymatrix
     first_entry = .FALSE.
  end if
  ! ...
end subroutine A

Вы можете сделать то же самое с mymatrix переменной модуля / хоста. Вы можете использовать сохраненный индикатор first_entry или положиться на пользователя (как в evets answer ), имеющем дополнительный шаг настройки:

module A_module
use constants
<declaration> myMatrix  ! Example with host association, automatically saved
contains
    subroutine A
    ! myMatrix is reused, either set up by a distinct call or on first entry
    ! other steps that use myMatrix
    end subroutine A
end module A_module

Или вы можете использовать переменную как фиктивный аргумент:

mymatrix_actual = ...
do k = 1,10000
  call A(mymatrix_actual)  ! A now has the dummy variable
end do
1 голос
/ 12 июля 2020

Конечно. Определите подпрограмму init_a_matrix, которая инициализирует матрицу вне do l oop.

subroutine init_a_matrix
   ! Do initialization here
end subroutine init_a_matrix

Тогда у вас есть

call init_a_matrix
do  k = 1,10000
    call A 
end do

Если вы хотите исключить избыточную инициализацию myMatrix в подпрограмме A (поскольку ее нужно вычислить только один раз при первоначальном вызове подпрограммы), вы можете использовать атрибут SAVE и LOGICAL флаг. В подпрограмме A вы делаете,

logical :: init_flag = .false.
real, save :: matrix_a(n,n)
if (init_flag .eqv. .false.) then
   ! Initialize matrix_a on the first call to the subroutine and reset init_flag.
   init_flag = .true.
end if
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...