Влияет ли чрезмерное использование вызовов функций на производительность? Конкретно в Фортране - PullRequest
5 голосов
/ 09 июля 2010

Я обычно пишу код с большим количеством функций, и мне кажется, что он понятнее.Но сейчас я пишу некоторый код на Фортране, который должен быть очень эффективным, и мне интересно, замедлит ли это чрезмерное использование функций или компилятор определит, что происходит и оптимизирует?

Я знаю, что в Java / Python и т. Д. Каждая функция является объектом, и поэтому для создания большого количества функций требуется, чтобы они создавались в памяти.Я также знаю, что в Haskell функции сводятся друг к другу, поэтому здесь нет особой разницы.

Кто-нибудь знает о случае с Фортраном?Есть ли разница в использовании намеренных / чистых функций / объявлении меньшего количества локальных переменных / чего-либо еще?

Ответы [ 4 ]

9 голосов
/ 09 июля 2010

Вызовы функций несут затраты производительности для стековых языков, таких как Fortran. Они должны добавить в стек и тому подобное.

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

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

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

2 голосов
/ 09 июля 2010

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

1 голос
/ 09 июля 2010

Я только что провел все утро, настраивая приложение, состоящее из смешанных C и Fortran, и, конечно, оно использует много функций.То, что я обнаружил (и то, что я обычно нахожу) не в том, что функции работают медленно, а в том, что определенные вызовы функций (и очень немногие из них) на самом деле не должны выполняться вообще .Например, очистка блоков памяти, просто чтобы быть аккуратной, но делать это с высокой частотой.

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

Что бы вы ни делали, выясните, что нужно исправить.Не думаюМногие люди не думают об этом вопросе как о догадке, но когда они задаются вопросом: «Будет ли это работать, поможет ли это?», Они ткнутся в темноте, а не выясняют гдепроблемы есть.Как только они узнают, где проблемы, исправление становится очевидным.

0 голосов
/ 09 июля 2010

Обычно вызовы подпрограмм / функций в Fortran будут иметь очень мало накладных расходов. Хотя в языковом стандарте не определены механизмы передачи аргументов, типичная реализация «по ссылке», поэтому копирование не требуется, а только установка новой процедуры. На большинстве современных архитектур это мало накладных расходов. Выбор хороших алгоритмов, как правило, гораздо важнее, чем микрооптимизация.

Исключением в отношении быстрого вызова может быть случай, когда компилятор должен создавать временные массивы, например, если фактический аргумент является несмежным подразделом массива, а аргумент вызываемой процедуры является простым непрерывным массивом. Предположим, что фиктивный аргумент является размерностью (:). Вызов его с массивом измерения (:) очень прост. Если вы запрашиваете неединичный шаг в вызове, например, массив (1: 12: 3), то массив не является смежным, и компилятору может потребоваться создать временную копию. Предположим, что фактическим аргументом является измерение (:, :). Если вызов имеет массив (:, j), подмассив является смежным, поскольку в Фортране первый индекс изменяется быстрее всего в памяти и не должен нуждаться в копии. Но массив (i, :) не является смежным и может потребовать временную копию.

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

...