Как решить проблему нехватки памяти в C ++, когда размер вектора слишком велик? - PullRequest
1 голос
/ 13 апреля 2020

Чтобы проверить, являются ли два вектора одинаковыми или нет

См. Код ниже

#include <iostream>
#include <vector>
#include <string>
int main(void) {
    std::vector<std::string> vstr1(131, "asdf");
    std::vector<std::string> vstr2(33131, "asdf");

    std::cout << (vstr1 == vstr2) << std::endl;;
    std::cout << "******************************" << std::endl;

    return 0;
}

Работает нормально.

Теперь я изменяю размер vstr2 быть очень большим , например 33333333333131

#include <iostream>
#include <vector>
#include <string>
int main(void) {
    std::vector<std::string> vstr1(131, "asdf");
    std::vector<std::string> vstr2(33333333333131, "asdf");

    std::cout << (vstr1 == vstr2) << std::endl;;
    std::cout << "******************************" << std::endl;

    return 0;
}

Не работает, и сообщение об ошибке

terminate called after throwing an instance of 'std::bad_alloc' 
what()  std::bad_alloc
Aborted    (core dumped)     a.out

У меня есть собран ошибка происходит из-за сбоя выделения памяти.

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

1 Ответ

9 голосов
/ 13 апреля 2020

У вас есть две проблемы:

1) Если для каждого std::string требуется только 1 байт ОЗУ для хранения, ваш вектор из 33333333333131 строк потребует около 30 терабайт данных. В действительности для каждого std:string требуется несколько десятков байтов (как минимум), поэтому требования будут даже больше, чем это. Вы вряд ли будете иметь столько ОЗУ (или пространства подкачки) на вашем компьютере.

2) Если ваш компьютер работает в 32-битном режиме, вы (как правило) ограничены менее чем 2 ^ 32 байт (или 4 гигабайта) адресного пространства для вашего процесса - может быть, немного меньше, или, может быть, несколько гигабайт больше, если на вашем компьютере включены специальные приемы подкачки. Так что в этом случае, даже если у вас было 30+ ТБ ОЗУ, вы не сможете получить доступ ко всему этому напрямую.

Что касается того, как обращаться с очень большими структурами данных, такими как тера-вектор Обычный порог, который нужно учитывать, это то, ожидаете ли вы, что у вас будет достаточно физической оперативной памяти, чтобы вместить все данные в оперативную память. Если вы это сделаете, то отлично - просто используйте вектор (или любую другую структуру данных в памяти, которая вам нравится) и используйте ее. Если нет, вы все равно можете избежать использования структуры данных в памяти, если вы настроили достаточно пространства подкачки для хранения данных, но поскольку дисковый ввод-вывод значительно медленнее, чем ОЗУ, вы можете обнаружить, что он слишком медленный для вашего цели.

Если вы не можете уместить структуру данных в ОЗУ, у вас есть несколько вариантов:

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

  2. Удерживать данные на диске, а не в ОЗУ, и загружать только часть их на время, оперируй им и выпиши результаты. (на самом деле это всего лишь разновидность (1))

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

  4. Отойдите назад и заново рассмотрите проблему, которую вы пытаетесь решить. Действительно ли требуется столько данных для хранения? Почему? Есть ли возможный альтернативный способ решения проблемы, который уменьшит требования к хранилищу? Если вам нужно хранить терабайты данных, вы, вероятно, либо точно знаете, что делаете (и поэтому, вероятно, не будете задавать вопросы об этом в StackOverflow), либо делаете что-то крайне неэффективное.

  5. (В крайнем случае) Купите больше оборудования для хранения. Вы можете получить компьютер с 30 терабайтами дискового хранилища и половиной терабайта оперативной памяти всего лишь за цену нового Ferrari в наши дни, так что вырубитесь! :)

...