Разница во встроенных функциях компилятором или компоновщиком? - PullRequest
15 голосов
/ 10 мая 2011

Мне интересно, есть ли какая-либо разница между встроенными функциями на уровне компоновщика или на уровне компилятора с точки зрения скорости выполнения?

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

Полагаю, это может зависеть от компилятора, и в этом случае меня больше всего интересуетв Visual C ++ (Windows) и gcc (Linux).

Спасибо

Ответы [ 4 ]

3 голосов
/ 10 мая 2011

Как правило, к моменту запуска компоновщика ваш исходный код уже скомпилирован в машинный код. Работа линкеров состоит в том, чтобы собрать все фрагменты кода и link вместе (возможно, исправить адреса по пути). В таком случае нет места для выполнения встраивания.

Но еще не все потеряно. Gcc предоставляет механизм для оптимизации времени компоновки (используя опцию -flto) при компиляции и компоновке. Это заставляет gcc создавать байт-код, который затем может быть скомпилирован и скомпонован компоновщиком в один исполняемый файл. Поскольку байт-код содержит больше информации, чем оптимизированный машинный код. Компоновщик теперь может выполнять радикальную оптимизацию на целом кодовой базе. То, что компилятор не может сделать.

См. здесь для получения более подробной информации о gcc. Не уверен насчет VC ++.

3 голосов
/ 10 мая 2011

Общее правило при прочих равных условиях - чем ближе к выполнению (компиляция-> линкование -> (возможно, JIT) -> выполнение), выполняется оптимизация, тем больше данных у оптимизатора и тем лучше оптимизация, которую он может выполнить.Поэтому, если оптимизатор не работает, вы должны ожидать лучших результатов, когда компоновщик выполняет встраивание - компоновщик узнает больше о контексте вызова и выполнит лучшую оптимизацию.

1 голос
/ 10 мая 2011

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

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

Причина, по которой оба варианта все еще доступны, заключается в том, что LTO может занимать большой объем оперативной памяти иПроцессор - у меня было VC ++ занимать несколько минут на связывание большого проекта C ++ раньше.Иногда не стоит включать, пока вы не отправите.Вы также можете исчерпать адресное пространство в достаточно большом проекте, так как он должен загружать весь этот байт-код в ОЗУ.

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

0 голосов
/ 10 мая 2011

Если функция встроена , разницы не будет.

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

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

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

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