2017-03-17 35 views
3

Big file compression with pythonは、例を使用する方法に関する非常に良い例を示しています。 bz2は純粋にPythonで非常に大きなファイルセット(または大きなファイル)を圧縮するためのものです。Pythonで並列gzip圧縮を行うにはどうすればよいですか?

pigzは、並列圧縮を利用するとより効果的だと言います。 純粋なPythonコードでは、私の知る限り(そしてGoogle検索)、私はPythonと同等の機能を見つけることができません。

pigz相当の並列Python実装がありますか?

+0

標準ライブラリの圧縮モジュールは、純粋なpython *ではありません。それらを調べると、共有ライブラリ(Cで書かれています)へのインターフェイスであることがわかります。 –

+2

そして、おそらく 'gzip'をリタイアする時が来ました。新しい 'zstd'圧縮は、gzipよりも[一般的に高速です](http://rsmith.home.xs4all.nl/miscellaneous/evaluating-zstandard-compression.html)、圧縮ファイルは小さくなります。 –

+1

@RolandSmith:もちろん、 Pythonインタフェースもありません。それは 'gzip'よりも速く見えますが、" compress faster "というオプションがたくさんあります。互換性の問題のおかげで、 'gzip'は少なくとも部分的には固執します。 10年以上前のハードウェア/ソフトウェアを持つシステムで解凍することができます。デフォルトでは、おそらくインストールされています( 'bz2'がほぼ普及していて、' xz'がそこに届いています)。データを多くの関係者に配布するには、移植性と圧縮率がスピードよりも重要です。一時的な圧縮の場合、速度はしばしば圧縮率に勝るので、 'lz4'または' lzo'は 'zstd'を上回るかもしれません。 – ShadowRanger

答えて

4

私は、pigzのPython用のインタフェースを知らないが、本当に必要な場合は、書くのは難しくないかもしれない。 Python's zlib moduleは任意のバイトのチャンクを圧縮することを可能にし、the pigz man pageは圧縮と出力フォーマットを既に並列化するためのシステムを記述する。

あなたが本当に並列圧縮が必要な場合は、大規模なIPC費用を負担しませんので、multiprocessing APIのスレッド担保バージョンmultiprocessing.dummy.Pool.imapmultiprocessing.dummyに包まれた塊を圧縮するzlibを用いた等価pigzで実装することが可能なはずですチャンクをワーカーに送り、ワーカーからチャンクを送信して)圧縮を並列化します。 zlibは、CPUバインド作業中にGILをリリースする数少ない組み込みモジュールの1つであるため、スレッドベースの並列処理の利点を実際に得ることができます。

実際には、圧縮レベルがそれほど高くならない場合、I/Oはしばしば実際の圧縮と同程度(同程度かそれ以下)です。データソースが実際にスレッドを圧縮するよりも速くフィードできない場合は、並列化の効果はほとんどありません。

+0

チャンクをワーカーに送る必要はありません。それぞれの作業者にファイルから自分のチャンクを読み込ませるだけです。またはUNIXでは、プールを作成する前に入力*用のメモリマップファイルを作成することができます。 OSの仮想メモリシステムは、入力ファイルのページをメモリに保持するために大部分を行います。 –

+0

@RolandSmith:True。私はすべてのことのための 'mmap'の大ファンであり、' zlib.compress'はバッファプロトコルに優しいと思われます(つまり、 'mmap'の' memoryview'から読み込み、データのコピーを避けることができます)。あなたはまだ 'imap'を使ってブロックを引っ張って作業を調整し、出力を整理したいでしょう(圧縮されたブロックのサイズはあらかじめ推測することができないので、書き込みを直列化することもできます)。 – ShadowRanger

+0

調整に関しては、各128kBブロックの先頭にバイトオフセットのリストを作成し、その上に「imap」を作成します。出力に関しては、私はおそらく、それぞれの圧縮されたブロックを一時的な出力ファイルに書き込んで、それらを後で連結させるでしょう。あるいは、 'mmap'を試してみてください。それを親プロセスに戻す*準最適です。 –

2

Z_SYNC_FLUSHflush()オペレーションを使用して、最後のデフレートブロックを完了し、バイト境界で終了することができます。連結した最後のストリームがZ_FINISH(これはflush()のデフォルト)でフラッシュされている限り、それらを連結して有効なデフレートストリームを作成できます。

また、CRC-32を並列で計算することもできます(zipまたはgzipのどちらでも、実際は並列gzip圧縮を意味すると思います)。 Pythonはzlibのcrc32_combine()関数へのインタフェースを提供していません。しかし、zlibからコードをコピーしてPythonに変換することができます。それは頻繁に実行する必要はないので、それは十分に速いでしょう。また、必要なテーブルをあらかじめ構築しておくことで、より高速にすることができます。また、固定ブロック長の行列をあらかじめ構築することもできます。

関連する問題