Программирование >>  Обобщенные обратные вызовы 

1 ... 47 48 49 [ 50 ] 51 52 53 ... 84


Задача 25. inline Сложность: 7

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

Вопрос для новичка

1. Что такое встраивание (inlining)?

Вопрос для профессионала

2. Когда выполняется встраивание? Может ли оно выполняться:

а) во время написания исходного текста?

б) во время компиляции?

в) во время компоновки?

г) при инсталляции приложения?

д) в процессе работы?

е) в некоторое другое время?

3. Дополнительный вопрос: какого рода функции гарантированно не будут встраиваемыми?

Решение

Какой ответ выберете вы на второй вопрос? Если вы выберете ответы а) или б), то вы не одиноки. Это наиболее распространенные ответы на данный вопрос, и в книге [Sutter02] я уже вкратце обращался к этой теме. Но если бы тема этим и исчерпывалась, то мы могли бы на этом завершить рассмотрение задачи и отправиться на пикник. Но на этот раз пикника не будет. У настоящего мужчины всегда найдется что сказать. Причем сказать можно достаточно много.

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

Краткий обзор

1. Что такое встраивание (inlining)?

Если вы читали [Sutter02], то вы можете пропустить этот и несколько следующих подразделов и перейти сразу к разделу Ответ В: во время компоновки на стр. 171.

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

пример 25-1

double sguareC double х ) { return х * х; } int main С) {

double d = SquareC 3.14159 * 2.71828 );

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

Задача 7.1 в русском издании книги. - Прим. ред. 168 Оптимизация и эффективность



int main О {

const double temp = 3.14159 * 2.71828; double d = temp * temp;

Такое встраивание устраняет излишние расходы на выполнение вызова функции, а именно - на внесение параметров в стек, переход процессором в другое место памяти для выполнения кода функции, что, помимо затрат на переход, может привести к полному или частичному сбросу кэша инструкций процессора. Встраивание - это далеко не то же, что и трактовка Square как макроса, поскольку вызов встраиваемой функции остается вызовом функции, и ее аргументы вычисляются только один раз. В случае же макросов вычисление аргументов может выполняться неоднократно; так, макрос #define SquareMacro(x) С(х)*(х)) при вызове SquareMacro(3.14159 2.71828) будет раскрыт до (3.14159*2.71828)*(3.14159*2.71828) (т.е. умножение п на е будет выполнено не один раз, а два).

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

Между прочим, вы заметили, что в примере 25-1, который и.ллюстрирует встраиваемость, не использовано ключевое слово inline? Это сделано преднамере]ШО. Мы вернемся к этому моменту еще не раз в процессе рассмотрения основного вопроса задачи.

2. Когда выполняется встраивание? Может ли оно выполняться;

а) во время написания исходного текста?

б) во время компиляции?

в) во время компоновки?

г) при инсталляции приложения?

д) в процессе работы?

е) в некоторое другое время?

3. Дополнительный вопрос: какого рода функции гарантированно не будут встраиваемыми?

Ответ А; во время написания исходного текста

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

Когда вы намереваетесь написать ключевое слово inline в вашем исходном тексте, вы не должны забывать о трех важных вещах.

По умолчанию не делайте этого. Преждевременная оптимизация - зло, и вы не должны использовать inline до тех пор, пока профилирование не покажет необходимость этого в определенных случаях. Более полную информацию по этому вопросу можно найти в [Sutterf)2] или запросив на поисковом сервере типа Google что-то вроде преждевременная оптимизация или premature

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



site:www.gotw.ca - вы получите массу страшных предупреждений о прежде-временной оптимизации вообще и встраивании в частности.

Это означает всего лишь попробуйте, пожалуйста . Как описано в [Sutter02], ключевое слово inline -- всего лишь подсказка для компилятора, возможность попытаться мило поговорить с ним, предоставляемая языком программирования (далее будут описаны недостатки таких милых разговоров). Ключевое слово inline вообще не имеет никакого семантического действия в программе на С++. Оно не влияет на другие конструкции языка, на использование функции, объявленной inline (например, вы можете получить адрес такой функции), и нет никакой стандартной возможности программно определить, объявлена ли данная функция как встраиваемая или нет.

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

> Рекомендация

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

Ответ Б: во время компиляции

Обычно во время работы компиляторы сами, без внешней подсказки, выполняют описанный в примере 25-1 вид встраивания.

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

Не делая встроенными вызовы функций, которые вы объявили как inline.

Делая встроенными вызовы функций, которые вы не объявляли встраиваемыми.

Встраивая некоторые из вызовов, оставляя другие вызовы той же функции обычными невстраивасмыми (независимо от того, объявлена ли функция как inline).

Вернемся к примеру 25-1 и обратим внимание на то, что в нем нигде не говорится, что функция должна быть встраиваемой. Это сделано преднамеренно, потому что этим я хотел проиллюстрировать тот факт, что встраивание все равно может произойти, даже без объявления функции inline. Не удивляйтесь, если ваш сегодняшний компилятор поступит именно так. Поскольку вы не можете написать соответствующую стандарту программу, которая выявит отличия при встраивании функции компилятором, этот способ оптимизации оказывается совершенно законным, и компилятор может (а часто и должен) выполнять его за вас.



1 ... 47 48 49 [ 50 ] 51 52 53 ... 84

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика