Чистый вектор на каждой итерации цикла. Какой самый эффективный способ памяти?

У меня вопрос по поводу std::vector.

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

Что из следующего лучше

for ( ... ) {
  std::vector<Type> my_vector;
  my_vector.reserve(stuff_count);
  // Do stuff , and append stuff to my_vector.
}

Или это:

std::vector my_vector;
for ( ... ) {
  my_vector.clear();
  my_vector.reserve(stuff_count);
  // Do stuff , and append stuff to my_vector.
}

Пожалуйста, скажите мне, что лучше, или если есть еще лучший способ делать вещи.

Заранее большое спасибо!

9 ответов

Решение

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

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

Я предвижу, что прогнозирование размеров вектора и резервирование достаточного количества памяти для векторов заранее поможет мне значительно сократить использование памяти.

Попробуйте действовать как инженер, а не как гадалка. Создайте тест и измерьте разницу.

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

Второй может быть немного быстрее, но я нахожу первый чище.

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

эээ... что?! Это не имеет никакого смысла. Резервирование памяти никак не помогает уменьшить использование памяти. Это предотвращает необходимость постоянного перераспределения, что ускоряет процесс, но с точки зрения использования вы не получаете никакой выгоды.

Я бы сказал, что это немного зависит от того, как Type должен быть построен / разрушен. Если это POD, который не требует уничтожения, вы можете пропустить clear(), которая вызывает все деструкторы в цикле, и использовать его вместо статического массива:

std::vector<Type> my_vector(size);
for (...)
{
  int index = 0;
  // Do stuff
  my_vector[index] = some_value;
}

(Предупреждение: код не проверен)

Второй будет использовать максимальный объем памяти из всех используемых в цикле, т. Е. Максимальный размер типов stuff_count. std::vector::clear() не обязательно свободная память. Т.е. если ты позвонишь std::vector::capacity() до и после std::vector::clear() стандартная соответствующая реализация может вернуть то же значение.

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

std::vector<type>().swap(my_vector);
my_vector.reserve(stuff_count); 

Или ваше первое решение, так как общий эффект будет таким же.

Как насчет?

std::vector<DataType> my_vector;
my_vector.resize(sizeof(yourData));
memcpy(reinterpret_cast<char*>(&my_vector), &yourData, sizeof(yourData));

Если вам нужно выполнить много добавлений, используйте std::deque вместо std::vector и просто используйте "push_back".

Другие вопросы по тегам