LINUX.ORG.RU

Релиз shuf-t 1.2 — аналог shuf для файлов размером с RAM

 ,


2

12

Хочу представить публике утилиту shuf-t — аналог shuf (случайная перестановка строк файла) из GNU Core Utilities, предназначенный для работы с текстовыми файлами, размеры которых сравнимы или превышают доступную RAM.

Факты:

  • Shuf-t был написан с нуля на Qt5. Версия 1.2 перенесена на boost 1.5.8, без Qt. Но QtCreator \ qmake все еще используются для сборки.
  • Распространяется под лицензией Simplefied BSD.
  • Командный интерфейс совместим с shuf.
  • На данный момент доступен только deb пакет. Windows версия будет собрана позднее.
  • Для тасования строк использован алгоритм Фишера-Йетса

Кому мал shuf?

Основная сфера применения shuf-t — задачи машинного обучения. Конкретнее - подготовка данных для Vowpal Wabbit. Машинное обучение позволяет классифицировать (и не только) результаты на основе исторической выборки. Яркий пример — банковский скоринг (давать/не давать кредит). Чем больше результатов кредитования увидит классификатор — тем он точнее (обычно).

Столкнувшись с данными, объемом превосходящими RAM одного компьютера, экспериментатор вынужден обращаться к кластерам (MapReduce и т.п.) и облакам. Либо воспользоваться системами online machine learning, лучшей из которых сейчас является Vowpal Wabbit. Принцип VW — получил пример, обработал его и забыл. В памяти хранятся только коэффициенты результирующих уравнений, которые подгоняются по получаемым примерам. Т.о. VW может работать на одном ПК с наборами данных неограниченного размера.

У подобных систем есть минусы, и один из них — чувствительность к порядку предъявляемых для обучения классификатора данных. К примеру, если вы отсортируете ваш набор кредиторов по результату, и предъявите VW сначала 10000 неплательщиков, а затем 10000 исправно погасивших долг, то после обучения классификатор будет всех заносить в последнюю группу, т.к. о неплательщиках он давно «забыл». Выходом в данном случае является равномерное размазывание записей о плохих и хороших заемщиках по набору данных. Что и достигается рандомизацией порядка строк в текстовом файле размером в сотню гигабайт.

Как работает?

Очень просто - в RAM считываются не строки файла, а их адреса в нем. Их порядок рандомизируется. В соответствие с новым порядком строк исходный файл считывается в выделенный в RAM буфер и сохраняется, куда пожелал пользователь. Нюансом тут является то, что файл считывается в несколько проходов (т.к. буфер меньше его размера), а offset'ы строк сортируются так, что чтение всегда идет от начала файла к его концу. Т.е. не выполняется seek() адреса меньше текущей позиции чтения.

Скорость работы зависит от числа строк, их размера и меняется нелинейно. 4Гб файл с дефолтным буфером в 1Гб у меня обрабатывается 4 минуты.

>>> Проект на github



Проверено: Shaman007 ()
Последнее исправление: Truf (всего исправлений: 3)
Ответ на: комментарий от Truf

Это результат на SSD?

Не, на домашнем буке с буфером 1G. 128M хорош разве что для файла длин строк.

Результаты сильно смахивают на benchmark

Вот и здорово, ибо моё то пишет последовательно.

vodz ★★★★★
()
Ответ на: комментарий от quest

Читать однозначно через read()/pread() иначе тебя задолбайют пейдж-фолты. Это уже здесь обсудалось минимум два раза. А как писать - не настолько кртично.

cvv ★★★★★
()
Ответ на: комментарий от vodz

Попробовал на файле в 52Gb. В нем всего 12.1 млн строк, но их размер от 2000 до 4700 байт.
shuf-f оставил на ночь с буфером 4Gb - результат 158 мин.
shuf-t с буфером 2Gb запускал в фоне, гоняя youtube в FF - результат 162.5 мин. На чистое чтение всего файла он потратил 10мин 10 сек. И затем выполнил 26 проходов за 152 мин, т.е. 5.8 мин за проход. По всей видимости, благодаря большим размерам строк он продолжает получать выигрыш от seek'ов при чтении.
Для меня неожиданно, что производительность решения на mmap'ах падает схожим образом. Тем не менее, решение на split'ах в этой формулировке уложится, грубо, в 60 мин. Ради интереса, можно попробовать вариант с mmap только на запись, как предлагает cvv, но он тоже вряд ли будет лучше split'ов. И т.к. shuf-t на split'ы перевести довольно просто, если нигде нет ошибок и как руки дойдут, я перейду на него.

Truf
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.