Рассмотрим следующую глупую функцию:
void sum (vector<int>& vec, int* sumOut)
{
*sumOut = 0;
for(std::size_t i = 0; i < vec.size(); ++i)
{
*sumOut += vec[i];
}
}
Фактическая сгенерированная сборка будет зависеть от компилятора и реализации vector
, но я думаю, что в большинстве случаев компилятор должен перечитывать размер vector
из памяти каждый раз через цикл. Это связано с тем, что указатель sumOut
может потенциально перекрывать (псевдоним) внутреннее хранилище вектора размера (при условии, что vector
хранит его размер в целых числах), поэтому размер можно изменить в цикле. Если вы часто вызываете такую функцию, это может привести к большому количеству циклов, потому что вы касаетесь памяти больше, чем нужно.
Три возможных решения:
Сохранить размер в локальной переменной.
В идеале размер получится
хранится в реестре и избегать прикосновения
память в целом. Даже если это должно
получить в стек, компилятор
должен быть в состоянии заказать
загружает / хранит более эффективно.
Используйте __restrict
на выходе
указатель. Это говорит компилятору
что указатель не может
перекрывать что-либо еще, поэтому пишет
ничего не требует перезагрузки
еще.
Обратный цикл. Прекращение
условие теперь проверяется на 0
вместо этого vec.size()
никогда
позвонил снова.
Из них, я думаю, # 1 - самый чистый, но некоторые люди могут предпочесть # 3. # 2, вероятно, наименее удобен для читателя, но может быть быстрее других (поскольку это означает, что данные вектора могут быть прочитаны более эффективно).
Для получения дополнительной информации о псевдонимах см. Презентация Кристера Эриксона GDC по оптимизации памяти ; там есть пример, почти идентичный этому.