Почему const int быстрее, чем const int &? - PullRequest
4 голосов
/ 09 марта 2012

Однажды я заметил это случайно, и теперь решил тщательно его протестировать.

Итак, когда я вызываю функцию:

#define Type int
#define Prm const Type &
Type testfunc1(Prm v1, Prm v2, Prm v3, Prm v4, Prm v5, Prm v6, Prm v7, Prm v8, Prm v9, Prm v10){
    return (v1|v2|v3|v4|v5|v6|v7|v8|v9|v10);
}

100 миллионов раз:

        for(Type y = 0; y < 10000; y++){
            for(Type x = 0; x < 10000; x++){
                out |= testfunc1(x,y,x,x,y,y,x,y,x,y);
            }
        }

С типами int, const int и const int & я заметил, что const int быстрее, чем const int &. (Примечание: я использую возвращаемое значение, чтобы гарантировать, что функция не будет оптимизирована).

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

Мои тесты:

const int: 7.95s
const int &: 10.2s

Редактировать: Я думаю, что это действительно из-за моей архитектуры; Я проверил с типом Sint64 и результаты были:

const Sint64: 17.5s
const Sint64 &: 16.2s

Edit2: Или это? Протестировано с типом double (что является 64-битным?), И результаты вызывают у меня недоумение:

const double: 11.28s
const double &: 12.34s

Edit3: обновлен код цикла, чтобы он соответствовал моим новейшим тестам с 64-битными типами.

Ответы [ 3 ]

9 голосов
/ 09 марта 2012

Вводя аргумент &, вы добавляете больше кода в программу. Без & последовательность:

 push values
 call Function
 pop values <- usually an update to stack pointer

и в функции:

 return sp[arg1] | sp[arg2] | etc <- value read direct from stack.

Добавление '&' делает это:

 push address of value1
 push address of value2
 etc
 call Function
 pop values <- usually an update to stack pointer

и в функции:

 return_value = 0;
 address = sp[arg1]
 or return_value, [address]
 address = sp[arg2]
 or return_value, [address]
 etc
 return return_value

Итак, как видите, & добавляет много. Так зачем его использовать? Если у вас очень большой объект, передача указателя является более оптимальной, чем копирование объекта в стек.

7 голосов
/ 09 марта 2012

Этот результат сильно зависит от системы.Это указывает на то, что в вашей конкретной системе копирование значения ссылки (которое, скорее всего, реализовано как указатель) имеет более высокую стоимость, чем копирование значения целого числа.Наиболее вероятная причина такой разницы заключается в том, что для представления целого числа требуется 32-разрядное представление, а для представления указателя / ссылки требуется 64-разрядное значение. РЕДАКТИРОВАТЬ Это не говоря уже о стоимости доступа к вашим целым числам: получение их значений потребует дополнительной косвенности.Поскольку вы передаете только два элемента, использование кэширования в значительной степени скрывает эту дополнительную стоимость, но стоимость есть.

Вы абсолютно правы в отношении больших типов, хотя: передавая ссылку набольшой struct или vector<...> по-прежнему требует только 64 бита (или любого другого размера в вашей системе), независимо от того, сколько элементов имеет ваша структура или сколько элементов хранится в vector<...>.Чем больше структура, тем выше затраты на ее передачу по значению и, следовательно, экономия, которую вы получаете, делая ее эталонной.

1 голос
/ 09 марта 2012

Передача адресов вместо значений приводит к тому, что адреса уходят (ищите анализ побега или анализ точек в вашем любимом учебнике по компилятору), что усложняет оптимизацию.

Да, такие вещи, как встраивание и связываниеоптимизация может смягчить эти проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...