Работа с большими объемами данных в C ++ - PullRequest
11 голосов
/ 16 августа 2010

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

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

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

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

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

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

Ответы [ 6 ]

17 голосов
/ 16 августа 2010

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

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


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

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

2 голосов
/ 16 августа 2010

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

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

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

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

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

Некоторые ОС также имеют административный лимит на то, насколько большой может быть куча приложений.

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

Звучит так:

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

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

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

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

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

Данные переменной длины в файле - подкачка

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

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

Критерий поиска: "файл подкачки: C ++", добавьте больше или больше 2 ГБ для большего. НТН

1 голос
/ 16 августа 2010

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

0 голосов
/ 16 августа 2010

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

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

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

echo 2 > /proc/sys/vm/overcommit_memory
0 голосов
/ 16 августа 2010

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

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

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