“…Что же это делается? На дворе, можно сказать, уже давно 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). It 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 прислал мне теоретическую статью, посвящённую теоретическим аспектам параллельной архивации. За это ему огромное спасибо. Остаётся только пожалеть, что я не программист и не могу сам написать параллельный архиватор.
А что насчет RARа ? Он же есть под *никс и поддерживает многопоточность, если не ошибаюсь. Или тебе обязательно надо бесплатный?
P.S. Насчет “не напишу сам”. Был у нас в технаре один чел, на два курса старше меня, большой любитель всяческих теоретических изысков. И вот заинтересовали его как-то алгоритмы сжатия без потерь. Так он у меня на “Корвете” (кто не знает, был такой КУВТ “Корвет” на 8-битном проце) на “С” проверял работу алгоритма ZIPа (“деревья Хаффмана”, если мне память не изменяет). И попутно меня этим грузил. Было весело 🙂
1) Под *NIXами стандартами компрессии де-факто являются .Z, .gz и .bz2 – в силу своей совместимости с tarом. Отсюда и приходится плясать
2) Я не знаю, поддерживает ли поточность версия RAR под *NIXы
1. Увы, консольная версия ZIP-формат не поддерживает
2. Дык, возьми и проверь :-). Ссылку дать ?
Уведомление: И снова про параллельные архиваторы (pigz) | Блог FlyCat.Info: КОТорый летает...
Уведомление: Как ограничить число используемых процессоров (ядер) программе | Блог FlyCat.Info: КОТорый летает...