Я написал программу, которая должна обрабатывать очень большие данные со следующими библиотеками:
Итак, у меня проблемы с памятью (программа использует LOT), и я подумал, может быть, я смогу заменить эти библиотеки (на то, что уже существует или мои собственные реализации):
Итак, три вопроса:
std::vector
эффективна ли память Я не знаю о картах буста, но люди из Boost обычно знают, что делают, я сомневаюсь, что вы сэкономите много памяти, создав собственные варианты.
Вы можете сделать несколько других вещей, чтобы помочь с проблемами памяти:
Сегодня, когда память настолько дешева, что выделение 10 ГБ ОЗУ очень просто, я думаю, что ваши узкие места будут в обработке данных, а не в распределении данных.
Эти две статьи объясняют структуры данных, лежащие в основе некоторых распространенных реализаций неупорядоченных ассоциативных контейнеров:
Несмотря на то, что между реализациями есть некоторые различия, они скромны — самое большее одно слово на элемент. Если вы используете решения с минимальными накладными расходами, такие как отсортированные векторы, это даст вам 2-3 слова на элемент, даже не вдвое больше, если ваши объекты большие. Таким образом, вам, вероятно, лучше прибегнуть к среде с большим объемом памяти или радикально изменить свой подход, используя базу данных или что-то в этом роде.
Если у вас есть только один набор данных и несколько способов доступа к ним, вы можете попробовать использовать boost::multi_index
здесь документация.
std :: vector — это непрерывный массив, плюс несколько байтов служебных данных. Единственный способ улучшить работу с вектором — использовать меньший тип элемента. Можете ли вы хранить короткий int вместо обычного int? Если это так, вы можете сократить векторную память наполовину.
Возможно, вы используете эти контейнеры для хранения указателей на множество объектов в куче? Если это так, у вас может быть много потерянного пространства в куче, которое может быть сохранено путем написания пользовательских распределителей или путем полного устранения указателя на элемент кучи и сохранения типа значения в контейнере.
Посмотрите на ваши типы классов. Рассмотрите все типы указателей, и должны ли они быть динамическим хранилищем или нет. Типичный класс часто имеет члены-указатели, свисающие с базового объекта, что означает, что отдельный объект представляет собой граф кусков памяти сам по себе. Чем больше вы сможете использовать своих учеников, тем эффективнее вы будете использовать кучу.
ОЗУ дешево в 2014 году. Достаточно просто построить процессоры Intel x86-64 с 64-256 ГБ ОЗУ и твердотельным диском для быстрой замены, если текущая версия не подходит для проекта. Надеюсь, это не коммерческое настольное приложение, которое мы обсуждаем. 🙂
Я закончил, изменив boost::unordered_multimap
за std::unordered_map
из vector
,
boost::unordered_multimap
потребляет более чем в два раза больше памяти, std::unordered_map
из vector
из-за дополнительных указателей, которые он сохраняет (по крайней мере, один дополнительный указатель на элемент) и того факта, что он хранит ключ и значение каждого элемента, в то время как unordered_map
из vector
хранит ключ только один раз для вектора, который содержит все сталкивающиеся элементы.
В моем конкретном случае я пытался хранить около 4 000 000 целых чисел, потребляя около 15 ГБ памяти в идеальном случае. Используя мультикарту, я получаю более 40 ГБ, а при использовании карты я использую около 15 ГБ (чуть больше из-за указателей и других структур, но их размер, если это презренно).