У меня есть очень большой многомерный вектор, который изменяется в размере все время. Есть ли любая точка для использования vector.reserve () функция, когда я только знаю хорошее приближение размеров.
Так в основном у меня есть вектор
A[256*256][x][y]
куда x идет от 0 до 50 для каждого повторения в программе и затем обратно к 0 снова. Значения y могут отличаться каждый раз, что означает это для каждого из [256*256][y]
элементы вектор y могут иметь другой размер, но еще меньше, чем 256;
Таким образом для разъяснения моей проблемы это - то, что я имею:
vector<vector<vector<int>>> A;
for(int i =0;i<256*256;i++){
A.push_back(vector<vector<int>>());
A[i].push_back(vector<int>());
A[i][0].push_back(SOME_VALUE);
}
Добавьте элементы к вектору...
A.clear();
И после этого я делаю то же самое снова от вершины.
Когда и как я должен зарезервировать пространство для векторов. Если бы я понял это правильно, я сэкономил бы много времени, если я использовал бы резерв, поскольку я изменяю размеры все время?
Что было бы отрицательными / положительными сторонами резервирования максимального размера, мой вектор может иметь, который был бы [256*256][50][256]
в некоторых случаях.
BTW. Я знаю о различных Матричных Шаблонах и Повышении, но решил пойти с векторами на этом...
Править: Я также задавался вопросом, как использовать резервную функцию в многомерных массивах. Если я только зарезервирую вектор в двух размерах, то он затем скопирует все это, если я превышу его способность в третьем размере?
Чтобы помочь в обсуждении, вы можете рассмотреть следующие определения типов:
typedef std::vector<int> int_t; // internal vector
typedef std::vector<int_t> mid_t; // intermediate
typedef std::vector<mid_t> ext_t; // external
Стоимость роста (увеличение емкости вектора) int_t
будет влиять только на содержимое этого конкретного вектора и не повлияет на другие элементы. Стоимость увеличения mid_t
требует копирования всех сохраненных элементов в этом векторе, то есть для этого потребуется весь вектор int_t
, что намного дороже. Стоимость увеличения ext_t
огромна: для этого потребуется скопировать все элементы, уже хранящиеся в контейнере.
Теперь, чтобы повысить производительность, было бы гораздо важнее получить правильный размер ext_t
(в вашем вопросе он кажется фиксированным 256 * 256). Затем установите правильный размер промежуточного mid_t
, чтобы исключить дорогостоящие перераспределения.
Объем памяти, о котором вы говорите, огромен, поэтому вы можете рассмотреть менее стандартные способы решения вашей проблемы. Первое, что приходит в голову, - это добавление дополнительного уровня косвенности. Если вместо хранения фактических векторов вы удерживаете интеллектуальные указатели в векторах, вы можете снизить стоимость роста векторов mid_t
и ext_t
(если размер ext_t
фиксирован , просто используйте вектор mid_t
). Теперь это будет означать, что код, использующий вашу структуру данных, будет более сложным (или лучше добавить оболочку, которая позаботится об косвенных указаниях). Каждый вектор int_t
будет размещен в памяти один раз и никогда не будет перемещаться ни при перераспределении mid_t
, ни в ext_t
. Стоимость перераспределения mid_t
пропорциональна количеству выделенных векторов int_t
, а не фактическому количеству вставленных целых чисел.
using std::tr1::shared_ptr; // or boost::shared_ptr
typedef std::vector<int> int_t;
typedef std::vector< shared_ptr<int_t> > mid_t;
typedef std::vector< shared_ptr<mid_t> > ext_t;
Еще одна вещь, которую вы должны принять во внимание, это то, что std :: vector :: clear ()
не освобождает выделенное внутреннее пространство в векторе, а только уничтожает содержащиеся в нем объекты и устанавливает размер равным 0. То есть вызов clear ()
никогда не освободит память. Шаблон для фактического освобождения выделенной памяти в векторе:
typedef std::vector<...> myvector_type;
myvector_type myvector;
...
myvector.swap( myvector_type() ); // swap with a default constructed vector
Каждый раз, когда вы вставляете вектор в другой вектор, устанавливайте размер в конструкторе перемещаемых векторов:
A.push_back(vector<vector<int>>( somesize ));
Вы имеете рабочую реализацию, но обеспокоены исполнением. Если ваши профильные шоу это, чтобы быть узким местом, можно рассмотреть использование явного массива C-стиля целых чисел, а не вектора векторов векторов.
Видят how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c для примера
, можно снова использовать то же выделение каждый раз, перевыделение
луг по мере необходимости и в конечном счете хранение его в метке прилива использования.
, Если действительно векторы являются узким местом, исполнением вне предотвращения операций калибровки на векторах, каждое повторение цикла, вероятно, станет во власти вашей схемы доступа в массив. Попытаться получить доступ к самым высоким заказам последовательно.
Здесь - список встроенных функций MySQL для группы по агрегату
AVG () Возвращает среднее значение аргумента BIT_AND () Возврат побитово и BIT_OR () Возврат побитовым или BIT_XOR () (v4.1.1) Возврат побитового xor COUNT (DISTINCT) Возвращает число различных значений COUNT () Возвращает число возвращенных строк GROUP_CONCAT () (v4.1) Возврат конкатенированной последовательности MAX () Возвращает максимальное значение MIN () Возврат минимального значения STD () Возврат стандартного отклонения населения STDDEV_POP () (v5.0.3) Возврат стандартного отклонения населения STDDEV_SAMP () (v5.0.3) Возврат стандартного отклонения образца STDDEV () Возврат стандартного отклонения населения SUM () Возвращает сумму VAR_POP () (v5.0.3) Возврат стандартной дисперсии населения VAR_SAMP () (v5.0.3) Возврат дисперсии выборки VARIANCE () (v4.1) Возврат стандартной дисперсии заполнения
Я считаю, что вы хотите SUM ()
Когда слово «shall» используется в стандарте C++, оно означает «должен от боли смерти» - если реализация не подчиняется этому, она неисправна.
-121--1531935- Если во время построения известен размер вектора, передайте его в c 'tor и назначьте с помощью оператора []
вместо push _ back
. Если вы не полностью уверены в конечном размере, сделайте предположение (может быть, добавить немного больше) и используйте резерв
, чтобы вектор резервировал достаточно памяти заранее.
Каковы будут отрицательные/положительные стороны резервирования максимального размера моего вектора, который в некоторых случаях будет [256 * 256] [50] [256].
Отрицательная сторона: потенциальная трата памяти. Положительная сторона: меньше времени ЦП, меньше фрагментации кучи. Это компромисс между памятью и ЦП, оптимальный выбор зависит от вашего приложения. Если вы не привязаны к памяти (на большинстве потребительских машин более чем достаточно оперативной памяти), рассмотрите возможность предварительного резервирования.
Чтобы решить, сколько памяти резервировать, посмотрите на среднее потребление памяти, а не на пике (резервирование 256 * 256 * 50 * 256 не является хорошей идеей, если такие размеры не нужны регулярно)