Встроенная функция C ++ & amp; контекстная оптимизация

Я прочитал в книге Скотта Мейерса «Эффективный C ++», что:

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

Теперь вопрос: что такое контекстно-зависимая оптимизация и зачем она нужна?

4

Решение

Я не думаю, что «контекстно-зависимая оптимизация» — это определенный термин, но я думаю, что в основном это означает, что компилятор может анализировать сайт вызова и код вокруг него и использовать эту информацию для оптимизации функции.

Вот пример. Это, конечно, надумано, но оно должно продемонстрировать идею:

Функция:

int foo(int i)
{
if (i < 0) throw std::invalid_argument("");
return -i;
}

Звоните на сайт:

int bar()
{
int i = 5;
return foo(i);
}

Если foo составляется отдельно, он должен содержать код сравнения и выдачи исключений. Если это встроено в bar, компилятор видит этот код:

int bar()
{
int i = 5;
if (i < 0) throw std::invalid_argument("");
return -i;
}

Любой вменяемый оптимизатор оценит это как

int bar()
{
return -5;
}
6

Другие решения

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

Представь это:

bool callee(bool a){
if(a) return false;
else return true;
}

void caller(){
if(callee(true)){
//Do something
}
//Do something
}

После включения код будет выглядеть примерно так:

void caller(){
bool a = true;
bool ret;
if(a) ret = false;
else ret = true;

if(ret){
//Do something
}
//Do something
}

Что может быть оптимизировано и дальше:

void caller(){
if(false){
//Do something
}
//Do something
}

А затем:

void caller(){
//Do something
}

Функция теперь намного меньше, и у вас нет затрат на вызов функции и особенно (в отношении вопроса) стоимость ветвления.

2

Скажи, что функция

void fun( bool b) { if(b) do_sth1(); else do_sth2(); }

и это называется в контексте с предопределенным false параметр

bool param = false;
...
fun( param);

тогда компилятор может уменьшить тело функции до

...
do_sth2();
2

Я не думаю что контекстная оптимизация означает что-то конкретное, и вы, вероятно, не можете найти точное определение.

Хорошим примером будет классический метод получения некоторых атрибутов класса, без включения в него программы:

  1. прыгнуть в тело добытчика
  2. перенести значение в реестр (eax на x86 под окнами с настройками Visual Studio по умолчанию)
  3. вернуться к вызываемой
  4. переместить значение из eax к локальной переменной

При использовании встраивания можно пропустить практически всю работу и переместить значение непосредственно в локальную переменную.

Оптимизация строго зависит от компилятора, но многое может произойти (распределение переменных может быть пропущено, код может изменить порядок и т. Д.). Но вы всегда сохраняете call / jump, что является дорогостоящей инструкцией.

Больше чтения по оптимизации Вот.

0
По вопросам рекламы [email protected]