Оценка констант в для контура

for(int i = 0; i < my_function(MY_CONSTANT); ++i){
//code using i
}

В этом примере будет my_function(MY_CONSTANT) будет оцениваться на каждой итерации или будет сохраняться автоматически? Зависит ли это от используемых флагов оптимизации?

2

Решение

Это должно работать как будто функция вызывается каждый раз.

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

Например. это обычно происходит с звонками .end() для стандартных контейнеров.


Общий совет: если вы сомневаетесь, нужно ли микрооптимизировать фрагмент кода,

  1. Не делай этого.
  2. Если вы все еще думаете об этом, измерение.
  3. Ну, был третий момент, но я забыл, может быть, все еще подожду.

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

10

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

Будет оцениваться каждая итерация. Вы можете сэкономить дополнительное время вычислений, выполнив что-то вроде

const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
//code using i
}
3

Современный оптимизирующий компилятор под as-if rule может быть в состоянии оптимизировать вызов функции в случае, который вы указали в своем комментарий здесь. as-if rule говорит, что соответствующий компилятор только эмулирует наблюдаемое поведение, мы можем убедиться в этом, перейдя к черновому стандартному разделу C ++ 1.9 Выполнение программы который говорит:

[…] Скорее соответствующие реализации должны эмулировать (только)
наблюдаемое поведение абстрактной машины, как объяснено ниже.

Так что если вы используете постоянное выражение а также my_function не имеет видимых побочных эффектов, которые можно было бы оптимизировать. Мы можем собрать простой тест (увидеть это в прямом эфире на Godbolt):

#include <stdio.h>

#define blah 10

int func( int x )
{
return x + 20 ;
}

void withConstant( int y )
{
for(int i = 0; i < func(blah); i++)
{
printf("%d ", i ) ;
}
}

void withoutConstant(int y)
{
for(int i = 0; i < func(i+y); i++)
{
printf("%d ", i ) ;
}
}

В случае withConstant мы видим, что это оптимизирует вычисления:

cmpl    $30, %ebx   #, i

и даже в случае withoutConstant он выполняет вычисления вместо выполнения вызова функции:

leal    0(%rbp,%rbx), %eax  #, D.2605
2

Если my_function объявляется constexpr, а аргумент действительно является константой, значение вычисляется во время компиляции и, таким образом, соответствует правилам «как будто» и «последовательная согласованность без гонки данных».

constexpr my_function(const int c);

Если у вашей функции есть побочные эффекты, это не позволит компилятору переместить ее из for-loop так как он не будет выполнять правило «как будто», если только компилятор не сможет найти выход из него.

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

int my_function(const int c) {
return 17+c; // inline and constant reduced to the value.
}

Таким образом, ответ на ваш вопрос … возможно!

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