Делает ли Фортран копии секций массива, переданных в функцию / подпрограмму? - PullRequest
2 голосов
/ 05 марта 2020

При передаче разделов массивов в подпрограммы в Фортране, например, f(a, b, c(2:5,4:6)) (все из них 2D-массивы), программа сначала создает временную копию c, а затем передает ее подпрограмме (в качестве ссылки, указателя). , et c), или все это обрабатывается динамически?

Я пытаюсь преобразовать некоторый код на Фортране в C ++, и я вижу вызовы подпрограмм, в которых в качестве аргументов передаются секции массивов. Насколько мне известно, C ++ не позволяет этого, поэтому я попытался обойти это в C ++ следующим образом (mat2d = std::vector<std::vector<T>>):

f(mat2d &a, mat2d &b, mat2d *a, int rows, int rows, int offsetx, int offsety) {...}

и назвав его:

f(a, b, c.data(), ...)

Это работает но это требует размера (ов), а также смещения для случаев, когда я хочу сделать матричное умножение c (например). Итак, если Фортран сначала делает копию c(2:5,4:6) в (скажем) массиве temp(4,3), то я могу имитировать c, что в C ++: просто сделать копию во временную, а затем передать ссылку на эту временную функция, без строк / столбцов / смещений. Но если нет ... Я не против услышать мысли других людей.


Пример подпрограммы:

subroutine f(A, B, C)
  implicit none
  real(kind(1d0)) :: A(2,2), B(2,2), C(2,2)
  C = A*B
  return
end f

Если мои слова плохие, возможно, картинка с реальный код подойдет? Массивы: auxfour(4,4), aux44(4,4) и Gv(2,2).

code

А вот вызов, с auxp(5) и тем же Gv:

code2

Полная подпрограмма. Картинка, а не слова.

sub

1 Ответ

4 голосов
/ 05 марта 2020

Это правда, что стандарт Fortran не определяет детали механизма передачи. Однако, поскольку компиляторы пытаются быть эффективными, мы можем многое сказать о том, что обычно происходит на практике.

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

В некоторых случаях временная копия практически неизбежна.

Давайте рассмотрим

real :: a(10,10)

call f(a(2:5,4:6))

тогда, если f равно

subroutine f(c)
  real :: c(3,3)

, компилятор может сделать очень мало, временная копия практически гарантирована. То же самое верно для

subroutine f(c)
  real :: c(3,*)

Однако для предполагаемой формы массива

subroutine f(c)
  real :: c(:,:)

это не так. Эти аргументы передаются с использованием дескриптора массива и могут быть несмежными, и вы обычно не видите для них временных копий.

Наконец, если первое измерение завершено:

real :: a(2:5,10)

call f(a(:,4:6))

копия также не требуется, так как подмассив является непрерывным в памяти.


Даже если временная переменная не требуется, компилятор всегда может ее создать, ничто не гарантируется. Но это не очень вероятно на практике. Компиляторы стараются быть эффективными.

...