Алгоритм расчесывания бревен - PullRequest
14 голосов
/ 09 декабря 2008

Мы получаем эти файлы данных размером ~ 50 ГБ, состоящие из 16-байтовых кодов, и я хочу найти любой код, который встречается в 1/2% или более раз. Есть ли способ сделать это за один проход данных?

Изменить: Есть тонны кодов - возможно, что каждый код отличается.

ЭПИЛОГ: Я выбрал Дариуса Бэкона как лучший ответ, потому что я думаю, что лучший алгоритм - это модификация элемента большинства, с которым он связан. Алгоритм большинства должен быть изменяемым, чтобы использовать только небольшой объем памяти - например, 201 код, чтобы получить 1/2%, я думаю. В основном вы просто идете по потоку, считая до 201 различных кодов. Как только вы найдете 201 отдельный код, вы сбрасываете по одному на каждый код (вычтите 1 из счетчиков, забыв обо всем, что станет 0). В конце концов, вы отбрасываете самое большее N / 201 раз, поэтому любой код, встречающийся больше раз, должен все еще быть.

Но это алгоритм двух проходов, а не один. Вам нужен второй проход, чтобы подсчитать количество кандидатов. На самом деле легко понять, что любое решение этой проблемы должно использовать как минимум 2 прохода (первая партия загружаемых вами элементов может отличаться, и один из этих кодов может в итоге составлять ровно 1/2%)

Спасибо за помощь!

Ответы [ 6 ]

13 голосов
/ 09 декабря 2008

Metwally et al., Эффективное вычисление часто встречающихся и топ-k элементов в потоках данных (2005) . Были некоторые другие соответствующие документы, которые я прочитал для своей работы в Yahoo, которые я не могу найти сейчас; но это похоже на хорошее начало.

Редактировать: Ах, смотрите это Статья Брайана Хейса . Это наброски точного алгоритма из-за Demaine и др., Со ссылками. Он делает это за один проход с очень небольшим объемом памяти, получая набор элементов, включая те, которые вы часто ищете, если они существуют. Чтобы получить точное количество, требуется (теперь отслеживаемый) второй проход.

3 голосов
/ 09 декабря 2008

это будет зависеть от распределения кодов. если имеется достаточно небольшое количество различных кодов, вы можете создать ядро ​​http://en.wikipedia.org/wiki/Frequency_distribution с картой. в противном случае вам, вероятно, придется построить http://en.wikipedia.org/wiki/Histogram, а затем сделать несколько проходов по данным, проверяя частоты кодов в каждом сегменте.

2 голосов
/ 09 декабря 2008

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

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


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

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

Итак, вы знаете долю входных данных, связанных с каждым кодом.

Это в основном конвейер sort * | uniq -c

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

1 голос
/ 09 декабря 2008

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

1 голос
/ 09 декабря 2008

Если файлы состоят только из 16-байтовых кодов, и вы знаете, какой размер каждого файла, вы можете рассчитать количество кодов в каждом файле. Затем вы можете найти порог 0,5% и следовать любым другим рекомендациям для подсчета вхождений каждого кода, записывая каждый, частота которого пересекает порог.

1 голос
/ 09 декабря 2008

Это зависит от того, сколько существует различных кодов и сколько у вас памяти.

Моей первой идеей было бы создать хеш-таблицу счетчиков с кодами в качестве ключей. Переберите весь файл, увеличив счетчик соответствующего кода и посчитав общее число. Наконец, отфильтруйте все ключи со счетчиками, которые превышают (* total-counter 1/200).

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