2016-06-14 3 views
2

У меня есть огромное количество (1500 миллионов) пар Integer, где каждый из них связан с идентификатором документа. Теперь моя цель - поиск документов, имеющих одну пару.Память эффективная карта <пара <int,int>, комплект <int>> альтернативный

Моя первая идея состояла в том, чтобы использовать хэш-карту (std::map) с использованием значений пары в качестве ключей и документов идентификаторов в качестве ассоциированных значений, т.е. map<pair<int,int>, unordered_set<int>>

Например:

Document1 

- pair1: (3, 9) 
- pair2: (5,13) 

Document2 

- pair1: (4234, 13) 
- pair2: (5,13) 

map<pair<int,int>, unordered_set<int>> hashMap 
hashMap[{3, 9}].insert(1) 
hashMap[{5, 13}].insert(1) 

hashMap[{4234, 13}].insert(2) 
hashMap[{5, 13}].insert(2) 

приведет в

Key(3,9) = Documents(1) 
Key(5,13) = Documents(1,2) 
Key(4234,13) = Documents(2) 

Моя проблема в том, что это занимает огромное количество памяти, которая превышает мою доступную 24 ГБ ОЗУ. Поэтому мне нужна альтернатива с хорошей производительностью для вставок и поисковых запросов, которые могут вписаться в мою память. В теории я использую 1500 Million * 3 (PairVal1, PairVal2, Document-ID) * 4 (bytes per Integer) = 18GB, когда накладные расходы не учитываются. Итак, есть ли хорошие альтернативы для моей проблемы?

+0

std :: map нет хеш-карты, вы можете захотеть std :: unordered_map –

+0

Я не могу говорить об эффективности, но вы можете посмотреть на stxxl для этого типа проблем. Http: // stxxl.sourceforge.net/ – Dan

+0

Если количество документов в 'set' является небольшим, вы можете заменить его на' std :: vector' – Galik

ответ

0

Можете ли вы использовать файловую систему?

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

На всех входах/выходах вы должны будете совершить значительные штрафные санкции. Получайте как можно быстрее диск. Требования к хранилищу также значительно возрастут, поскольку имена каталогов, имена файлов и содержимое файла становятся символами ascii вместо двоичных целых чисел.

+0

Если вы используете диск, почему бы просто не иметь файл подкачки или зарезервированный распределитель 'mmap()'. Это должно иметь гораздо меньшие накладные расходы, чем файл для каждой записи. – joelw

+0

@joelw Поскольку 'mmap()' часто заметно медленнее, чем вызовы 'read()'/'write()' низкого уровня. http://marc.info/?l=linux-kernel&m=95496636207616&w=2 –

+0

@AndrewHenle Это решение не является низкоуровневым 'read()'/'write()' Каждое чтение будет обернуто 'open () '/' close() '. – joelw

0

Одно решение для сокращения пространства является вместо std::map<std::pair<int,int>, std::unordered_set<int>> использования std::unordered_map<int, std::unordered_set<int>>

Для обращенного std::pair<int, int> к int вы должны использовать функцию сопряжения, например:

Cantor’s Pairing Function

Очевидно вы ограничены используя меньшие числа в ваших парах.

Отображение для двух максимальных 16-разрядных знаковых целых чисел (32767, 32767) будет иметь значение 2147418112, что не соответствует максимальному значению для 32-битного целого числа.

Другой вариант создать свой собственный индексатор основе в B-Tree, или с использованием Open Source Search Engine библиотека как xapian, она написана на C++ и является быстрым и простым в использовании.

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

+1

Я думал об этом уже, проблема в том, что каждое значение пары может варьироваться от 0 до 1 миллиона. Я решил, что мне понадобится 1 млн. 1 млн. Возможностей отображения, которые превышают диапазон 'unsigned int', а переменная' unsigned long long' займет 8 байт. –

2

Возможно, это работа для встроенной базы данных, такой как SQLite или BerkeleyDB или Tokyo Cabinet.

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

+0

Я планировал это сделать, но опыт работы с базами данных hindsight не очень хорош, и я не хотел торопить все, что не сработало бы в конце. Поэтому я не уверен, сколько времени потребуется, чтобы вставить новые пары и перед проверкой, существует ли эта пара. Я могу себе представить, что эта операция будет очень дорогостоящей, имея 1500 миллионов строк. Есть ли у вас опыт в этом отношении? –

+0

@MadA. Я использовал Токийский кабинет для чего-то подобного лет назад, и он сделал 50 000 в секунду. –