Работа с большими объемами данных в c ++

У меня есть приложение, которое иногда использует большой объем данных. Пользователь имеет возможность загружать несколько файлов, которые используются в графическом отображении. Если пользователь выбирает больше данных, чем может обработать ОС, приложение вылетает довольно сильно. В моей тестовой системе это число составляет около 2 гигабайт физической ОЗУ.

Какой хороший способ справиться с этой ситуацией? Я получаю «плохое выделение» из новой и пытался перехватить это, но все равно столкнулся с крахом. Я чувствую, как будто я иду в грязных водах, загружая такое большое количество данных, но это требование этого приложения для обработки такого рода большой загрузки данных.

Редактировать: я сейчас тестирую под 32-битной системой Windows, но приложение будет работать в различных версиях Windows, Sun и Linux, в основном 64-битных, но некоторые 32.

Обработка ошибок не является сильной: она просто оборачивает основной код создания экземпляра блоком catch catch, который ищет любое исключение за жалобу другого сверстника на неспособность каждый раз ловить bad_alloc.

Я думаю, что вы, ребята, правы, Мне нужна система управления памятью, которая не загружает все эти данные в ОЗУ, просто кажется, что это так.

Edit2: Лютер сказал, что лучше. Спасибо, парень. Сейчас мне просто нужен способ предотвратить сбой, который при правильной обработке исключений должен быть возможен. Но в будущем я буду внедрять это решение о приемке.

11
задан Robb 16 August 2010 в 15:47
поделиться

6 ответов

Существует библиотека STXXL, которая предлагает STL-подобные контейнеры для больших наборов данных.

Замените "large" на "huge". Она разработана и оптимизирована для многоядерной обработки наборов данных, которые умещаются только на терабайтных дисках. Этого может быть достаточно для вашей проблемы, или реализация может стать хорошей отправной точкой для создания собственного решения.


Сложно сказать, что ваше приложение не работает, потому что существует множество сложностей, когда речь идет об условиях ограниченного объема памяти: Вы можете столкнуться с жестким ограничением адресного пространства (например, по умолчанию 32-битная Windows имеет только 2GB адресного пространства на пользовательский процесс, это можно изменить, http://www.fmepedia.com/index.php/Category:Windows_3GB_Switch_FAQ ), или быть съеденным заживо убийцей OOM (не мифический зверь:, см. http://lwn.net/Articles/104179/ ).

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

17
ответ дан 3 December 2019 в 05:56
поделиться

Как насчет поддержки таблицы заголовков вместо загрузки всех данных. Загружать актуальную страницу, когда пользователь запрашивает данные. Также используйте некоторые алгоритмы сжатия данных (например, 7zip, znet и т. Д.), Которые уменьшают размер файла. (В моем проекте размер уменьшен с 200 МБ до 2 МБ)

1
ответ дан 3 December 2019 в 05:56
поделиться

Я упоминаю об этом, потому что выше это было упомянуто лишь вкратце, но похоже, что « система подкачки файлов » может быть решением. Эти системы считывают большие наборы данных в « кусках », разбивая файлы на части. После написания они обычно « просто работают », и вам, надеюсь, больше не придется с ними возиться.

Чтение больших файлов

Данные переменной длины в файле - разбиение на страницы

Новая ссылка ниже с очень хорошим ответом.

Обработка файлов размером более 2 ГБ

Поисковый запрос: "язык подкачки файлов: C ++" добавьте большой или более 2 ГБ для большего. HTH

1
ответ дан 3 December 2019 в 05:56
поделиться

Установите 64-битный ЦП, 64-битную ОС и 64-битный компилятор и убедитесь, что у вас достаточно оперативной памяти.

32-разрядное приложение ограничено 2 ГБ памяти (независимо от того, сколько у вас физической памяти). Это связано с тем, что 32-битный указатель может адресовать 2 ^ 32 байта == 4 ГБ виртуальной памяти. 20 лет назад это казалось огромным объемом памяти, поэтому разработчики оригинальной ОС выделили 2 ГБ для работающего приложения и зарезервировали 2 ГБ для использования ОС. Чтобы получить доступ к более чем 2 ГБ, вы можете использовать различные уловки, но они сложны. Наверное, проще перейти на 64-битную.

-1
ответ дан 3 December 2019 в 05:56
поделиться

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

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

Вы должны убедиться, что отображение памяти выполняется в режиме только для чтения, чтобы операционная система могла удалить его из ОЗУ, если это необходимо для чего-то другого.

Если пользователь выбирает больше данных, чем может обработать ОС, приложение довольно сильно вылетает.

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

Некоторые ОС также имеют административное ограничение на размер кучи приложения.

В моей тестовой системе это число составляет около 2 гигабайт физической памяти.

Это звучит так:

  • ваше приложение 32-битное, а
  • ваша ОС использует разделение виртуальной памяти 2GB / 2GB.

Чтобы избежать превышения лимита, вам необходимо:

  • обновить приложение и ОС до 64-разрядной версии или
  • сообщить ОС (патч IIRC для Windows; в большинстве Linux он уже есть) использовать виртуальную память 3 ГБ / 1 ГБ расколоть. Некоторые 32-разрядные ОС используют разделение памяти 2 ГБ / 2 ГБ: 2 ГБ виртуальной памяти для ядра и 2 для пользовательского приложения.Разделение 3/1 означает 1 ГБ виртуальной машины для ядра, 3 - для пользовательского приложения.
2
ответ дан 3 December 2019 в 05:56
поделиться

Не уверен, что вы с этим сталкиваетесь, но если вы используете Linux, malloc обычно не приводит к сбою, а operator new обычно не выбрасывает bad_alloc. Это происходит потому, что Linux будет перекоммитить, и вместо этого убьет ваш процесс, когда решит, что системе не хватает памяти, возможно, при ошибке страницы.

См: Поиск в Google по запросу "oom killer".

Вы можете отключить это поведение с помощью:

echo 2 > /proc/sys/vm/overcommit_memory
0
ответ дан 3 December 2019 в 05:56
поделиться
Другие вопросы по тегам:

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