Является ли использование встроенной функции так же быстро, как прямое написание тела функции в коде? - PullRequest
1 голос
/ 03 января 2012
class MyClass
{
    public:
        MyClass()
        {
            m_dbLoopStart   = 0.0;
            m_dbLoopStop    = 100.0;
            m_dbLoopStep    = 0.001;
        }

        // Which of the following methods complete in a shorter time?

        void Foo1() const   // This one?
        {
            for (double x=m_dbLoopStart; x<=m_dbLoopStop; x+=m_dbLoopStep)
            {
                f(x);
            }
        }

        void Foo2() const   // Or, this one?
        {
            for (double x=m_dbLoopStart; x<=m_dbLoopStop; x+=m_dbLoopStep)
            {
                2.0 * x + 1.0;
            }
        }

    private:
        double m_dbLoopStart, m_dbLoopStop, m_dbLoopStep;

        inline static double f(double x)
        {
            return 2.0 * x + 1.0;
        }
};

Между Foo1() и Foo2(), какой из них завершится быстрее?

Ответы [ 4 ]

3 голосов
/ 03 января 2012

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

Как уже говорили другие, в этом случае это не будет иметь значения, при включенной оптимизации, даже цикл должен быть оптимизирован так, чтобы не было кода, при этом x присваивается значение m_dbLoopStop (независимо от того, может xбыть).

2 голосов
/ 03 января 2012

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

Так что строго теоретически, это быстрее.

1 голос
/ 17 января 2012

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

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

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

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

В моей практике программирования я использую небольшие (3 или менее строки) методы.Если я собираюсь встроить по соображениям производительности, я буду профилировать перед вставкой.

1 голос
/ 17 января 2012

Часто существуют небольшие семантические различия между вызовом встроенных функций с параметрами по сравнению с простым использованием кода копирования / вставки или #define макросов.Например, рассмотрим макрос и функцию:

extern void some_extern_function(int x);
#define foo1(x) (some_extern_function((x)), some_extern_function((x)))
void inline foo2(int x) {some_extern_function(x); some_extern_function(x); }

Теперь предположим, что их вызывают:

  extern volatile int some_volatile_int;
  foo1(some_volatile_int);
  foo2(some_volatile_int);

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

...