векторный резервный C++

У меня есть очень большой многомерный вектор, который изменяется в размере все время. Есть ли любая точка для использования 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. Я знаю о различных Матричных Шаблонах и Повышении, но решил пойти с векторами на этом...

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

5
задан 17 February 2010 в 13:15
поделиться

4 ответа

Чтобы помочь в обсуждении, вы можете рассмотреть следующие определения типов:

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
4
ответ дан 14 December 2019 в 13:34
поделиться

Каждый раз, когда вы вставляете вектор в другой вектор, устанавливайте размер в конструкторе перемещаемых векторов:

 A.push_back(vector<vector<int>>( somesize ));
2
ответ дан 14 December 2019 в 13:34
поделиться

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

Видят how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c для примера

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

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

0
ответ дан 14 December 2019 в 13:34
поделиться

Здесь - список встроенных функций 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 ()

-121--4541786-

Когда слово «shall» используется в стандарте C++, оно означает «должен от боли смерти» - если реализация не подчиняется этому, она неисправна.

-121--1531935-

Если во время построения известен размер вектора, передайте его в c 'tor и назначьте с помощью оператора [] вместо push _ back . Если вы не полностью уверены в конечном размере, сделайте предположение (может быть, добавить немного больше) и используйте резерв , чтобы вектор резервировал достаточно памяти заранее.

Каковы будут отрицательные/положительные стороны резервирования максимального размера моего вектора, который в некоторых случаях будет [256 * 256] [50] [256].

Отрицательная сторона: потенциальная трата памяти. Положительная сторона: меньше времени ЦП, меньше фрагментации кучи. Это компромисс между памятью и ЦП, оптимальный выбор зависит от вашего приложения. Если вы не привязаны к памяти (на большинстве потребительских машин более чем достаточно оперативной памяти), рассмотрите возможность предварительного резервирования.

Чтобы решить, сколько памяти резервировать, посмотрите на среднее потребление памяти, а не на пике (резервирование 256 * 256 * 50 * 256 не является хорошей идеей, если такие размеры не нужны регулярно)

0
ответ дан 14 December 2019 в 13:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: