#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: Совершенно бессмысленно задавать вопросы, связанные с производительностью, когда вы скомпилированы с отключенной оптимизацией. Предполагать, что компилятор будет выполнять оптимизацию (например, встроенные функции), даже если вы специально запросили, чтобы он не выполнял оптимизацию, попросту не имеет никакого смысла.