Параллельный архиватор pbzip2

«…Что же это делается? На дворе, можно сказать, уже давно XXI век! Компьютеры — все сплошь если не многопроцессорные, так хотя бы многоядерные или многопотоковые. И операционная система может использовать всё это великолепие для разбазаривания ресурсов CPU между процессами. Поэтому «нормальные» приложения могут и работать в несколько потоков и висеть одновременно (шутка). А между тем, самый обычный архиватор всю эту красоту использовать не может в принципе — он жмёт себе файл, хоть большой, хоть маленький — в один поток. И с этим нельзя ничего сделать?!» — так примерно рассуждали мы на работе, когда пытались «затоптать» очередной многогиговый лог-файл. Оказывается, поделать можно: среди разных архиваторов Avatar нашёл «параллельный» bzip2. Вот что о нём говорится на офсайте:

«PBZIP2 is a parallel implementation of the bzip2 block-sorting file compressor that uses pthreads and achieves near-linear speedup on SMP machines. The output of this version is fully compatible with bzip2 v1.0.2 or newer (ie: anything compressed with pbzip2 can be decompressed with bzip2). PBZIP2 should work on any system that has a pthreads compatible C++ compiler (such as gcc). has been tested on: Linux, Windows (cygwin & MinGW), Solaris, Tru64/OSF1, HP-UX, and Irix.»

Мой вольный перевод:

PBZIP2 — параллельное воплощение block-sorting архиватора bzip2, которое использует pthreads и архивирует почти с линейной скоростью на SMP-машинах (не знаю, как перевести, наверное правильнее будет «с линейной зависимостью от количества процессоров»).  Выходные данные этой версии полностью совместимы с bzip2 версий 1.0.2 или более поздних (то есть, всё зажатое pbzip2 может быть распаковано bzip2). pbzip2 может работать на любой системе с компилятором С++ совместимым с pthreads. Он проверен на Linux, Windows (cygwin и MinGW), Solaris, Tru64/OSF1, HP-UX, и Irix.

Скачиваем, распаковываем, говорим make. Для компиляции пакета необходимо иметь установленную libbz2-devel. Получаем исполняемый файл.

flycat@dt-0698:~/download/utils/pbzip2-1.0.2> ./pbzip2 -h
Parallel BZIP2 v1.0.2 - by: Jeff Gilchrist [http://compression.ca]
[July 25, 2007]             (uses libbzip2 by Julian Seward)

Invalid command line!  Aborting...

Usage: ./pbzip2 [-1 .. -9] [-b#cdfklp#qrtV] <filename> <filename2> <filenameN>
-b#      : where # is the file block size in 100k (default 9 = 900k)
-c       : output to standard out (stdout)
-d       : decompress file
-f       : force, overwrite existing output file
-k       : keep input file, don't delete
-l       : load average determines max number processors to use
-p#      : where # is the number of processors (default: autodetect)
-r       : read entire input file into RAM and split between processors
-t       : test compressed file integrity
-v       : verbose mode
-V       : display version info for pbzip2 then exit
-1 .. -9 : set BWT block size to 100k .. 900k (default 900k)

Example: pbzip2 -b15vk myfile.tar
Example: pbzip2 -p4 -r -5 myfile.tar second*.txt
Example: pbzip2 -d myfile.tar.bz2

Из встроенного хелпа следует, что архиватор имеет несколько режимов работы, умеет определять количество процессоров и разбрасывать по ним свои потоки архивации — как на автомате, так и при участии пользователя. Ну а теперь посмотрим его в действии. Итак, возьмём C2Duo:

flycat:/usr/src/pbzip2-1.0.2 # cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 15
model name      : Intel(R) Core(TM)2 CPU          6320  @ 1.86GHz
stepping        : 6
cpu MHz         : 1600.000
cache size      : 4096 KB
bogomips        : 3727.25
...

И запакуем гиговый файл со случайными данными:

newkis-app:/usr/src/pbzip2-1.0.2 # dd if=/dev/urandom of=test1 count=2000000 && time ./pbzip2 -v test1
2000000+0 records in
2000000+0 records out
1024000000 bytes (1.0 GB) copied, 248.5 seconds, 4.1 MB/s
Parallel BZIP2 v1.0.2 - by: Jeff Gilchrist [http://compression.ca]
[July 25, 2007]             (uses libbzip2 by Julian Seward)

         # CPUs: 2
 BWT Block Size: 900k
File Block Size: 900k
-------------------------------------------
         File #: 1 of 1
     Input Name: test1
    Output Name: test1.bz2

     Input Size: 1024000000 bytes
Compressing data...
    Output Size: 1028577585 bytes
-------------------------------------------

     Wall Clock: 236.037725 seconds

real    3m56.040s
user    7m38.193s
sys     0m11.525s

А теперь — обычным bzip2:

newkis-app:/usr/src/pbzip2-1.0.2 # dd if=/dev/urandom of=test1 count=2000000 && time bzip2 test1
2000000+0 records in
2000000+0 records out
1024000000 bytes (1.0 GB) copied, 249.193 seconds, 4.1 MB/s

real    5m43.496s
user    5m38.157s
sys     0m5.028s

Как видно, разница — почти 4 минуты против почти 6 — где-то в полтора раза. Неплохо. А теперь попробуем на двухпроцессорном (по 4 ядра каждый) Xeon-е:

real    0m29.855s
user    3m46.554s
sys     0m9.017s

и

real    3m20.551s
user    3m18.160s
sys     0m2.404s

30 секунд и 3,5 минуты — разница впечатлает! И зависимость от числа ядер — почти линейная. В общем архиватор pbzip2, конечно стоящий. Единственное, чего ему не хватает — он не может брать исходные данные из потока (хотя писать на stdout умеет). И ожидать эту полезную «фичу» придётся долго. Вот что выяснил Avatar в ходе своей переписки: «На днях, переписываясь, с разработчиком, было выяснено, что одна из самых нужных функциональностей («Add support for input from stdin & pipes»), обещанных в следующем релизе, появиться очень и очень не скоро из-за сильной загруженности разработчика». Жаль, конечно, идея очень и очень своевременная и нужная…

Всё тот же Avatar прислал мне теоретическую статью, посвящённую теоретическим аспектам параллельной архивации. За это ему огромное спасибо. Остаётся только пожалеть, что я не программист и не могу сам написать параллельный архиватор.

Параллельный архиватор pbzip2: 5 комментариев

  1. А что насчет RARа ? Он же есть под *никс и поддерживает многопоточность, если не ошибаюсь. Или тебе обязательно надо бесплатный?

    P.S. Насчет «не напишу сам». Был у нас в технаре один чел, на два курса старше меня, большой любитель всяческих теоретических изысков. И вот заинтересовали его как-то алгоритмы сжатия без потерь. Так он у меня на «Корвете» (кто не знает, был такой КУВТ «Корвет» на 8-битном проце) на «С» проверял работу алгоритма ZIPа («деревья Хаффмана», если мне память не изменяет). И попутно меня этим грузил. Было весело 🙂

    • 1) Под *NIXами стандартами компрессии де-факто являются .Z, .gz и .bz2 — в силу своей совместимости с tarом. Отсюда и приходится плясать
      2) Я не знаю, поддерживает ли поточность версия RAR под *NIXы

  2. Уведомление: И снова про параллельные архиваторы (pigz) | Блог FlyCat.Info: КОТорый летает...

  3. Уведомление: Как ограничить число используемых процессоров (ядер) программе | Блог FlyCat.Info: КОТорый летает...

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *