Производительность встроенной функции

#c #performance #function #inline

#c #Производительность #функция #встроенный

Вопрос:

У меня небольшая проблема с производительностью встроенной функции. Рассмотрим следующий код:-

 inline int left(int x) {
    return 2*x;
}
inline int right(int x) {
    return 2*x 1;
}

main() {
    for(int i=0;i<200000000;i  ) {
        int L=left(i);
        int R=right(i);
    }
}
  

Это при компиляции и выполнении (с флагом finline-функции и без него) занимает на моем компьютере около 1,90 секунды. Однако, когда я заменяю встроенные функции макросами, это занимает всего 1,26 секунды.
Хотя крайне маловероятно, что функция будет выполнена 200 миллионов раз, но все же я хотел бы знать, можно ли в любом случае достичь такой производительности с использованием встроенных функций?

РЕДАКТИРОВАТЬ: Получив пару оскорбительных комментариев, я понял, что не совсем ясно сформулировал свой вопрос. Я просто хотел знать, как добиться такой же производительности без использования каких-либо флагов оптимизации. Конечно, разумнее просто использовать -O2 или -O3, я просто хотел научиться.

Комментарии:

1. Вы включили оптимизацию? Вы находитесь в режиме отладки или выпуска?

2. Когда я переключаю оптимизатор на -O3, цикл полностью прекращается.

3. @alex : В этом нет ничего странного, потому что он определяет время отладочной сборки, и при этом следует ожидать нерелевантных / бессмысленных временных интервалов.

4. В конце концов, inline — это всего лишь предложение. Некоторые компиляторы могут игнорировать это при генерации кода.

5. Синхронизация отладочных сборок — против этого должен быть закон!

Ответ №1:

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

__attribute__((always_inline))

к объявлению вашей функции. (Также смотрите документы gcc здесь):

Как правило, функции не являются встроенными, если не указана оптимизация. Для функций, объявленных встроенными, этот атрибут вводит функцию, даже если уровень оптимизации не был указан.

Ответ №2:

Для меня, с GCC 4.2.1 при -O3 оптимизации, нет разницы во времени выполнения между встроенной функцией и макрокомандой. В любом случае это 0,185 секунды, и я серьезно сомневаюсь, что мой ноутбук в 10 раз быстрее вашего компьютера.

Запуск g -S далее показывает, что объектный код идентичен.

Я настроил int L и int R на volatile int , чтобы заставить его фактически выполнить цикл.

Редактировать: Цель более низких настроек оптимизации — помочь в отладке. Одна из причин, по которой встроенная функция может работать медленнее -O0 , заключается в том, что компилятор следит за тем, чтобы все переменные находились в согласованном состоянии, которое вы можете остановить и просмотреть в отладчике, в строке кода внутри встроенной функции.

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

Комментарии:

1. Как я уже говорил ранее. Когда я компилирую ее с использованием флага -O1, время выполнения составляет 0,00 секунды в обоих случаях. Я просто хочу объяснить, почему встраивание здесь неэффективно.

2. @jack: Если время стремится к нулю , как вы делаете вывод, что встраивание неэффективно?

3. @jack: Может быть, GCC просто игнорирует ваш -finline-functions флаг, когда вы находитесь в режиме отладки, и отказывается встроить функции? Недостаточно знаю GCC, но звучит возможно.

4. @Guy Sirton : Это было бы ужасно для библиотек только для заголовков (таких как подавляющее большинство библиотек boost ), которые должны помечать каждое определение функции как встроенное, чтобы избежать нарушения ODR.

5. @Jack: Совершенно бессмысленно задавать вопросы, связанные с производительностью, когда вы скомпилированы с отключенной оптимизацией. Предполагать, что компилятор будет выполнять оптимизацию (например, встроенные функции), даже если вы специально запросили, чтобы он не выполнял оптимизацию, попросту не имеет никакого смысла.