Неявное распределение по присваиванию против явного распределения / освобождения - PullRequest
0 голосов
/ 05 февраля 2019

Я могу перераспределить выделяемую переменную или массив без явной процедуры освобождения / выделения, как описано в Автоматическое выделение массива при назначении в Fortran , если мой компилятор Fortran 2003 соответствует.Например,

integer, allocatable :: i(:)

i = [1,2,3]
i = [1,2,3,4,5]

по сравнению со старым ( Fortran 90 ) способом:

if( allocated(i) ) deallocate(i)
allocate(i(3))
i = [1,2,3]
if( allocated(i) ) deallocate(i)
allocate(i(5))
i = [1,2,3,4,5]

Какие или преимущества и недостатки этой новой техники?Это, конечно, гораздо более лаконичный код, чем старый.Но есть ли причины отдавать предпочтение старому?Я все еще вижу старый способ в примерах кода гораздо больше, чем новый, но, возможно, это только потому, что Fortran 90 все еще используется больше, чем Fortran 2003.

В качестве быстрой проверки синхронизации я зациклил приведенный выше код 100 000 000 разпод gfortran 4.8.5 и обнаружил, что новый способ также, кажется, быстрее, работает около 4 секунд (новый путь) против 6 секунд (старый путь).И наоборот, в комментариях ниже @roygvib получает по существу противоположный результат с gfortran 8.2.

Также обратите внимание на недавнее обсуждение этого вопроса здесь: Фортранская дискуссионная группа

Ответы [ 2 ]

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

Я перечислю различия, то, что является преимуществом или недостатком, является субъективным.

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

Для тех, которые не используются для динамических языков, где большинство назначений выполняют какое-то распределение, может быть существенным фактом, что в операторах deallocate и reallocate этоявно видно, что перераспределение действительно происходит.

При автоматическом перераспределении компилятор может потенциально использовать realloc, особенно в случаях, подобных a = [a, 1].Но, насколько я знаю, компиляторы в настоящее время не делают этого.Тем не менее, обычный malloc будет часто использовать память там, где находился старый массив, если он там помещается.

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

Преимущество заключается в краткости кода.

integer, allocatable :: i(:)

i = [1, 2, 3]

имеет на одну строку меньше, чем

integer, allocatable :: i(:)

allocate(i(3))
i = [1, 2, 3]

Кроме того, вам не нужно явно указывать размер выделения,поэтому немного меньше избыточной информации.

Неудобным является то, что это автоматическая функция.

Я могу легко вспомнить два сценария, в которых эта функция является недостатком.

  1. Массив i перераспределяется при назначении по уважительным причинам (т.е. не является ошибкой в ​​коде) и вводит штраф за производительность, который может быть труднее найти.
  2. Массив i перераспределяетсяиз-за логической ошибки в коде.Эту ошибку было бы легче обнаружить, если последующий доступ к памяти из-за границы вызвал ошибку: -)

Вы можете обнаружить «2» с помощью проверок компилятора и решить «1» с помощью профилировщика,хоть.Так что, если у вас нет веской причины не использовать эту функцию, я бы сказал «используйте ее».Однако для существующих кодовых баз нет особой мотивации удалять операторы allocate «просто потому что».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...