С++ 64-битный int: передать по ссылке или передать по значению

Это вопрос эффективности о 64-битных целых числах. Предполагая, что мне не нужно изменять значение параметра «int», я должен передать его по значению или ссылке.

Предполагая 32-битную машину:

1) 32-битное целое число: я предполагаю, что ответ "передавать по значению", поскольку "передача по ссылке" потребует дополнительных затрат на поиск в памяти.

2) 64-битный int: если я передаю по ссылке, я передаю только 32-битный адрес в стеке, но мне нужен дополнительный поиск в памяти. Так какой из них лучше (референс или ценность)?

А если машина 64 битная?

С уважением,

JP


person Community    schedule 10.11.2010    source источник
comment
эффективность :( KISS. Передайте это, как вы передаете любое другое чертово целое число.   -  person    schedule 10.11.2010
comment
Компилятор, вероятно, все равно оптимизирует его.   -  person Pedro d'Aquino    schedule 10.11.2010
comment
@pst: +1 за забавный комментарий. чувак, я очень сильно смеялся.   -  person ali_bahoo    schedule 10.11.2010
comment
Любой приличный 32-битный генератор кода передает значение в два регистра ЦП или просто 8 байтов в кадре стека. То же самое верно для структуры, например. Вы не должны думать о передаче указателя, пока он не станет больше 16 байт.   -  person Hans Passant    schedule 10.11.2010
comment
@Hans: Спасибо за четкий и конкретный комментарий к моему вопросу.   -  person    schedule 10.11.2010


Ответы (5)


Пройти по значению - обязательно. Если система 64-битная, это означает, что она очень быстро копирует 64-битное слово.

person Armen Tsirunyan    schedule 10.11.2010

Даже на 64-битной машине передача по значению лучше (с очень немногими исключениями), потому что ее можно передать как значение регистра.

person Curd    schedule 10.11.2010
comment
Я бы сказал особенно на 64-битной машине. - person cHao; 10.11.2010
comment
Таким образом, передача 64-битного int по значению более эффективна, чем передача 64-битного int по ссылке как на 32-битных, так и на 64-битных машинах (тем более на 64-битных машинах), верно? - person ; 10.11.2010
comment
Мне любопытно узнать об исключениях (это не выходит за рамки обсуждения :) - person ; 10.11.2010
comment
@ JP19: я не уверен, что есть такие исключения. Возможно, таким исключением может быть следующая ситуация: у вызывающей стороны так много локальных переменных, что не все они могут храниться в регистрах, а адрес параметра использовался недавно, поэтому он все еще присутствует в регистре. Но это слишком эзотерические предположения; наверное не стоит рассматривать... - person Curd; 10.11.2010

Передайте их как boost::call_traits<int64_t>::param_type. В этом шаблоне собраны лучшие практики передачи любого типа на поддерживаемых платформах. Следовательно, на 32- и 64-битных платформах он будет другим, но вы можете использовать один и тот же код везде. Он работает даже внутри других шаблонов, где вы еще не знаете точный тип.

person MSalters    schedule 10.11.2010
comment
+1 это, безусловно, лучшее наказание для людей, беспокоящихся об оптимизации передачи целых чисел, что им приходится набирать эту партию. - person Steve Jessop; 10.11.2010
comment
Возможно, это правда, что для 64-битных данных разница незначительна. Тем не менее, дух вопроса стоит imo. Что делать, если у меня есть 12-байтовая структура? 16 байт? Комментарий Ханса Пассана, хотя и не может быть технически проверен или протестирован, по крайней мере, дает указание в правильном направлении. - person ; 10.11.2010
comment
Конечно, полезно знать, что для 64-битной не нужно беспокоиться :). (Хотя наш код будет вызывать такие функции сотни миллионов раз и в целом работает часами. В этом случае всегда полезно следовать рекомендациям). - person ; 10.11.2010

Используйте немного здравого смысла,

  1. если для объекта требуется сложный конструктор копирования, вероятно, стоит передать по ссылке (говоря, что довольно много объектов boost предназначены для передачи по значению, а не по ссылке просто потому, что внутренняя реализация довольно тривиальна) Есть один странный что я не очень разобрался, std::string, я всегда передаю это по ссылке...

  2. Если вы собираетесь изменить переданное значение, используйте ссылку

  3. В противном случае, ПЕРЕДАЧА ПО ЗНАЧЕНИЮ!

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

Оптимизировать, беспокоясь о том, как передается int, все равно, что ссать в море...

person Nim    schedule 10.11.2010

Ради аргумента давайте проигнорируем тривиальный случай удаления различий оптимизаторами. Предположим также, что вы используете 64-битные соглашения о вызовах Intel для Microsoft (которые отличаются от Linux ABI), тогда у вас есть 4 64-битных регистра для передачи таких значений, прежде чем вам придется прибегнуть к их проталкиванию в стек. Это явно лучше.

Для 32-битного приложения по значению и они попадут прямо в стек. Вместо этого по ссылке можно поместить указатель в регистр (опять же, несколько таких случаев использования регистра разрешены до обращения к стеку). Мы можем сделать это в некотором выводе g++ -O3 -S, вызвав f1(99) по значению и f2(101) по константной ссылке:

void f1(int64_t);
void f2(const int64_t&);

int main()
{
    f1(99);
    f2(101);
}

...

    pushl   0
    pushl   $99
    call    _Z2f1x    // by value - pushed two halves to stack

    leal    -8(%ebp), %eax
    movl    %eax, (%esp)
    movl    $101, -8(%ebp)
    movl    $0, -4(%ebp)
    call    _Z2f2RKx   // by const& - ugly isn't it!?!

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

Узел для совета pst...

"эффективность" :( KISS. Передайте это, как вы передаете любое другое чертово целое число. - pst

... хотя иногда вы применяете KISS к параметрам шаблона и делаете их все константами T&, хотя некоторые из них могут вписываться в регистры....

person Tony Delroy    schedule 10.11.2010