Улучшает ли вызов константы по ссылке производительность при применении к примитивным типам?

Что касается объектов (особенно строк), вызов по ссылке выполняется быстрее, чем вызов по значению, поскольку при вызове функции не требуется создавать копию исходного объекта. Используя const, можно также гарантировать, что ссылкой не злоупотребят.

Мой вопрос в том, работает ли вызов const по ссылке быстрее при использовании примитивных типов, таких как bool, int или double.

void doSomething(const string & strInput, unsigned int iMode);
void doSomething(const string & strInput, const unsigned int & iMode);

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

Дополнительный вопрос: влияет ли встраивание на ответ на мой вопрос?


person Fabian    schedule 19.03.2015    source источник
comment
В большинстве случаев эффекта не должно быть. Но профилирование для конкретного случая было бы хорошо. Я передаю примитивные типы по значениям и объекты по константной ссылке. Встраивание ничего не должно изменить.   -  person Mohit Jain    schedule 19.03.2015
comment
Важно понимать, что это не одно и то же (см. stackoverflow.com/questions/4705593/int -vs-const-int например). Выберите тот, который соответствует вашим потребностям - если передачи по значению достаточно, сделайте это - если требуется передача по ссылке, то сделайте это.   -  person Sander De Dycker    schedule 19.03.2015


Ответы (5)


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

Настройка производительности на основе догадок работает примерно в 0% случаев в C ++ (это внутреннее чувство, которое я испытываю к статистике, обычно это работает ...)

Верно, что const T& будет меньше, чем T, если sizeof(T) > sizeof(ptr), поэтому обычно 32-битное или 64-битное, в зависимости от системы.

Теперь спросите себя:

1) Сколько встроенных типов больше 64 бит?

2) Разве копирование 32-битного кода не стоит того, чтобы сделать код менее понятным? Если ваша функция становится значительно быстрее из-за того, что вы не копировали в нее 32-битное значение, возможно, это не так много?

3) Вы действительно настолько умны? (предупреждение о спойлере: нет.) См. этот отличный ответ по той причине, почему это почти всегда плохая идея: https://stackoverflow.com/a/4705871/1098041

В конечном итоге просто переходите по стоимости. Если после (тщательного) профилирования вы обнаруживаете, что какая-то функция является узким местом, а всех других оптимизаций, которые вы пробовали, было недостаточно (и вы должны попробовать большинство из них до этого), переходите к const-reference.

Тогда смотри, что это ничего не меняет. переворачиваться и плакать.

person Félix Cantournet    schedule 19.03.2015

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

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

Так что даже для «небольших объектов» может быть быстрее просто передать значение.

(Я прочитал это в очень хорошей книге: Компьютерные системы: взгляд программистов)

Еще несколько интересных обсуждений по теме попаданий / промахов в кеш: Как написать код, который лучше всего использует кэш ЦП для повышения производительности?

person Emile Vrijdags    schedule 19.03.2015

В 64-битной архитектуре нет примитивного типа - по крайней мере, в C ++ 11 - который больше, чем указатель / ссылка. Вы должны проверить это, но интуитивно понятно, что для const T& должно быть столько же данных, сколько для int64_t, и меньше для любого примитива, где sizeof(T) < sizeof(int64_t). Поэтому, поскольку вы можете измерить любую разницу, передача примитивов по значению должна быть быстрее , если ваш компилятор делает очевидную вещь --- вот почему я подчеркиваю, что если вам нужна определенность здесь, вы должны написать тестовый пример.

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

person uckelman    schedule 19.03.2015

const - это ключевое слово, которое оценивается во время компиляции. Это не влияет на производительность во время выполнения. Подробнее об этом можно прочитать здесь: https://isocpp.org/wiki/faq/const-correctness

person Martin Komischke    schedule 19.03.2015
comment
const не может отрицательно повлиять на производительность, так как это чисто время компиляции. Однако это может иметь положительный эффект с умными компиляторами. - person stefan; 19.03.2015

Меня учили:

  • Передача по значению, если переменная аргумента является одним из основных встроенных типов, например bool, int или float. Объекты этих типов настолько малы, что передача по ссылке не приводит к повышению эффективности. Также, если вы хотите сделать копию переменной.

  • Передайте постоянную ссылку, если вы хотите эффективно передать значение, которое не нужно изменять.

  • Передайте ссылку только в том случае, если вы хотите изменить значение переменной аргумента. Но стараться по возможности избегать изменения переменных аргументов.

person James    schedule 19.03.2015