Оптимизация времени соединения и встроенный
По моему опыту, существует много кода, который явно использует встроенные функции, которые возникают при компромиссе:
- Код становится менее кратким и несколько менее ремонтопригодным.
- Иногда инкрустация может значительно увеличить производительность во время выполнения.
- Вкладывание определяется в определенный момент времени, возможно, без ужасного хорошего предвидения его использования или без учета всех (будущих) окружающих обстоятельств.
Вопрос: оптимизирует ли привязка времени (например, в GCC) вручную, например, объявляет в C99 функцию "встроенный" и обеспечивает реализацию, устаревшую? Верно ли, что нам не нужно рассматривать встроенную функцию для большинства функций? Что относительно функций, которые всегда извлекают выгоду из встраивания, например, deg_to_rad (x)?
Уточнение: я все равно не думаю о функциях, которые находятся в одной и той же системе перевода, но о функциях, которые должны логически находиться в разных единицах перевода.
Обновление: я часто видел оппозицию против "inline", и было предложено устареть. Лично, однако, я часто вижу явно встроенные функции: как функции, определенные в теле класса.
Ответы
Ответ 1
Даже с LTO компилятору все же приходится использовать эвристику, чтобы определить, включать ли функцию для каждого вызова (обратите внимание, что оно принимает решение не за функцию, а за вызов). Эвристика учитывает такие факторы, как: - это в цикле, разворот цикла, насколько велика функция, как часто она называется глобально и т.д. Компилятор, безусловно, никогда не сможет точно определить, как часто вызывается код, и может ли расширение кода, возможно, выдувать тайники инструкций/трассировки/петли/микрокода конкретного процессора во время компиляции.
Профильная оптимизация должна быть шагом к решению этой проблемы, но если вы когда-либо пробовали ее, вы, вероятно, заметили, что вы можете получить колебание в производительности порядка 0-2%, и это может быть в любом направлении!:-) Это еще работа.
Если ваша конечная цель - это ваша конечная цель, и вы действительно знаете, что делаете, и действительно делаете тщательный анализ своего кода, то, что действительно нужно, - это способ рассказать компилятору о встроенном или нет встроенном для каждого вызова базис, не подсказка для каждой функции. На практике я справился с этим, используя специальные типы компилятора типа "force_no_inline" для случаев, которые я не хочу встраивать, и отдельную копию "force_inline" (или макрос в редком случае это не удается) для функции, когда я хочу, чтобы она была встроена, Если кто-то знает, как сделать это более чистым способом с конкретными подсказками компилятора (для любых компиляторов C/С++), сообщите мне.
Чтобы конкретно указать свои баллы:
1. Код становится менее кратким и несколько менее ремонтопригодным.
Как правило, нет - это только подсказка для ключевого слова, которая контролирует, как она встроена. Однако, если вы прыгаете через обручи, как я описал в последнем абзаце, тогда да.
2. Иногда встраивание может значительно увеличить производительность во время выполнения.
При выходе компилятора на свои устройства - да, конечно, может, но в основном этого не делает. У компилятора есть хорошая эвристика, которая делает хорошие, хотя и не всегда оптимальные решения. Специфически для ключевого слова компиляторы могут полностью игнорировать ключевое слово или использовать ключевое слово как слабый намек - в целом они кажутся неблагоприятными для наложения кода, который красным флагам их эвристики (например, вложение функции 16k в цикл с разверткой 16x).
3.Илинизация определяется в определенный момент времени, возможно, без ужасного хорошего предвидения ее использования или без учета всех (будущих) окружающих обстоятельств.
Да, он использует статический анализ. Динамический анализ может исходить из вашего понимания, а вы вручную контролируете встраивание на основе каждого вызова или теоретически из PGO (который все еще сосет).
Ответ 2
Возникает вопрос: оптимизирует ли связь времени (например, в GCC)? например, объявление на C99 функции "inline" и предоставление реализации, устаревшее?
Эта статья, похоже, ответит "Да:"
Подумайте на минуту: что превращает функцию в хорошего кандидата для встраивание? Помимо фактора размера, оптимизатор должен знать, как часто эта функция вызывается, откуда она вызывается, сколько других функции в программе являются жизнеспособными кандидатами для встраивания и - верьте или нет - называется ли функция когда-либо. Оптимизация (то есть встраивание), функция, которая не называется даже однажды, представляет собой времени и ресурсов. Но как оптимизатор может знать, что функция никогда не звонил? Ну, это не может. Если он не сканирует весь программа. Именно здесь [критическая оптимизация ссылок] становится решающей.
Ответ 3
Если оптимизация времени ссылки была такой же быстрой, как оптимизация времени компиляции, тогда это устраняет необходимость в подсказках компилятора. К сожалению, это, как правило, не быстрее, чем оптимизация времени компиляции, поэтому это компромисс между общей скоростью сборки и общим качеством оптимизации для этой сборки.
Кроме того, при определении функций в заголовках вам все равно нужно использовать inline. В противном случае вы получите ошибки компоновщика для нескольких определений этих функций, если они используются в нескольких единицах перевода.
Ответ 4
- Я не думаю, что ключевое слово inline влияет на ремонтопригодность и только едва хватает. (Мнение)
- Иногда inline может снизить производительность во время выполнения: http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.3
- Компиляторы довольно умны в инкрустации, я слышал, что Visual Studio почти полностью их игнорирует и решает встроить себя.
does link-time optimization render manual inlining, obsolete?
Совсем нет, оптимизатор, который делает ключевое слово inline без устаревших ударов в пути до времени ссылки.
Ответ 5
Пункт 33 - Скотт Майерс - 2-й Эд - Эффективный С++ - это на ум.
Вы должны иметь в виду ключевое слово static wrt inline! Теперь есть гнездо шершней!