Какова лучшая практика, когда функция Фортрана возвращает массив? - PullRequest
0 голосов
/ 22 февраля 2019

Скажем, я хочу написать функцию, которая принимает в качестве входных данных массив x одного измерения и возвращает другой массив y того же измерения на основе этого (чтобы проиллюстрировать это I 'м, используя функцию, которая умножает его на 2).У меня есть два варианта для этого кода:

function times2(x) result(y)
    real, intent(in) :: x(:)
    real, allocatable :: y(:)

    allocate(y(size(x))
    y = 2*x
end function

или

function times2(x,n) result(y)
    real, intent(in) :: x(n)
    integer, intent(in) :: n
    real  :: y(n)

    y = 2*x
end function

Лично я предпочитаю первый, потому что проще использовать для звонящего, но яЯ не уверен, что лучше с точки зрения памяти, предположим, что массив х может быть огромным, я не знаю, лучше ли быть отложенным массивом или автоматическим массивом.В любом случае, что является хорошим способом сделать это в современном Фортране?

1 Ответ

0 голосов
/ 23 февраля 2019

Вероятно, ни того, ни другого, хотя, как обычно, с этими вещами, ответ зависит от конкретных обстоятельств.

Предполагая неэлементарную операцию, я бы хотел написать такую ​​функцию (в модуле) как:

function times2(x) result(y)
  real, intent(in) :: x(:)
  real :: y(size(x))

  y = 2*x
end function

Выше есть аргумент фиктивной фигуры с автоматическим результатом функции.Это:

  • доступно при записи в стандарт Fortran 95;

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

  • может (или не может) избегать промежуточных копий значения массива;

  • может (или не может) требовать места для результата функции или эквивалентного временного в стеке.

Если бы операция была элементарной (то есть той же самой операцией для каждого элемента, как в данном примере), я бы написал элементальную функцию.Источник для такой функции принимает скалярный аргумент и предоставляет неразмещаемый скалярный результат без указателя.

elemental function times2(x) result(y)
  real, intent(in) :: x
  real :: y

  y = 2*x
end function

Обычно я использую результаты функции отложенной формы, когда форма (или некоторый другой атрибут)результат функции не может быть описан простым выражением спецификации.Результаты для распределенной функции:

  • требует записи по крайней мере в стандарт Fortran 2003;

  • может потребовать дополнительной пары выделения / освобождения кучи памяти выше, чемстрого необходимо, что может (или не может) влиять на производительность;

  • может не требовать такого же использования стека, как случай автоматического результата, который может (или не может) избегатьпроблемы переполнения стека во время выполнения.

Детали реализации компилятора (включая параметры компилятора) влияют на сравнение.В частности, различия в том, как компилятор управляет памятью для временных файлов, могут сделать два подхода сходными с точки зрения их требований к выделению стека и кучи.

Избегайте использования фиктивных аргументов массива фигур, если у вас нет особых требований.

...