Сохранение большого списка для тестирования членства в C - PullRequest
2 голосов
/ 15 января 2011

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

У меня есть алгоритм, который производит 9 731 643 264 таких элементов, и я хочу посмотреть, сколько из них уникально.Я предполагаю, что самое большее 1/36 из них будет уникальным, но не уверен.

При таком размере я не могу сделать это в памяти (так как у меня всего 4 гигабайта), поэтому мне нужен способ сохранить список из них, выполнить тесты на членство и добавить каждый новый, еслиэто еще не там.

Я работаю в C (gcc) на Linux, поэтому было бы хорошо, если бы решение могло работать оттуда.

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 15 января 2011

Это напоминает мне о некоторых проблемах, с которыми я столкнулся, работая над решением "Knight's Tour" много лет назад.(Математическая задача, которая теперь решена, но не мной.)

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

Для хранения списка на диске потребуется приблизительно 0,75 Терабайта.,,4 гигабайта памяти или нет, вам все равно нужен огромный диск, чтобы просто их вместить.И вам понадобится вдвое больше диска или больше, чтобы выполнить решения по сортировке / слиянию, о которых я говорю ниже.

Если бы вы могли СОРТИРОВАТЬ этот список, то вы могли бы просто бросить список по одному элементу за раз, просматриваядля уникальных копий рядом друг с другом.Конечно, для сортировки такого большого количества данных потребуется специальная процедура сортировки (которую вы написали), поскольку она является двоичной (покрытие шестнадцатеричным форматом удвоит размер ваших данных, но позволит использовать стандартные процедуры).,,хотя, вероятно, даже там они, вероятно, подавятся таким большим количеством данных.,,так что вы вернулись к своим собственным процедурам.

Некоторые вещи, о которых стоит подумать:

  1. Сортировка такого большого количества данных займет недели, месяцы или, возможно, годы.Хотя вы можете выполнять хорошую сортировку кучи или что-то еще в памяти, потому что у вас достаточно много дискового пространства, вы, скорее всего, будете делать «пузырьковые» файлы независимо от того, что вы делаете в памяти.

  2. В зависимости от того, как выглядит ваш алгоритм генерации, вы можете сгенерировать данные «одной загрузки», отсортировать их на месте и записать на диск в файле (отсортировано).Как только это будет сделано, вам просто нужно «объединить» все эти отдельные отсортированные файлы, что намного проще (даже если бы было 1000 файлов, это все равно было бы относительно проще).

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

  4. Конечно, сокращение данных - это всегда хорошо.Например, вы говорите о хэше 120, но имеет ли он обратимый характер?Если так, сортируйте хеш, так как он меньше.Если нет, то хеш может не сильно помочь (по крайней мере, для моих решений по сортировке).

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

1 голос
/ 15 января 2011

Вы, вероятно, можете значительно упростить свою жизнь, если наложите некоторые ограничения на свои входные данные: даже если предположить, что только 120 значащих битов, большое количество повторяющихся значений предполагает неравномерное распределение, так как равномерное распределение сделает дублирование маловероятным длязаданный размер выборки 10^10:

2^120 = (2^10)^12 > (10^3)^12 = 10^36 >> 10^10

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

Что бы я сделал:

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

Затем необходимо объединить отдельные файлы, что можно сделать в режиме онлайн, т. е. по мере появления файлов,Таким же образом работает сортировка слиянием на основе стека: сопоставьте каждому файлу счетчик, равный числу диапазонов в файле, и поместите каждый новый файл встек.Когда файл в верхней части стека имеет счетчик, больший или равный предыдущему файлу, объедините файлы в новый файл, счетчик которого представляет собой число диапазонов в объединенном файле.

...