2017-03-17 120 views
3

Big file compression with python給出了一個很好的例子,說明如何使用例如bz2純粹用Python來壓縮非常大的一組文件(或一個大文件)。如何用Python實現並行gzip壓縮?

pigz說,你可以做到通過利用並行壓縮更好。 據我所知(和谷歌搜索),我找不到在純Python代碼中這樣做的Python等價物。

是否有pigz或同等並行Python實現?

+0

標準庫中的壓縮模塊不是*純python *。如果你看看它們,你會發現它們是共享庫(用C語言編寫的)的接口。 –

+2

這可能是退休'gzip'的時候了。新的'zstd'壓縮比gzip [通常更快](http://rsmith.home.xs4all.nl/miscellaneous/evaluating-zstandard-compression.html),併產生更小的壓縮文件。 –

+1

@RolandSmith:當然,它也沒有Python接口。它看起來比'gzip'快,但有很多「壓縮速度更快」的選項。 「gzip」至少部分歸咎於兼容性問題;你可以在擁有10多年曆史的硬件/軟件的系統上解壓縮它,並且它可能是默認安裝的('bz2'幾乎和普通的一樣,'xz'到達那裏)。爲了向多方分發數據,可移植性和壓縮比比速度更重要。對於瞬態壓縮,速度通常會壓縮比率,所以'lz4'或'lzo'可能會超過'zstd'。 – ShadowRanger

回答

4

我不知道pigz接口爲Python的副手,但它可能不是那麼難寫,如果你真的需要它。 Python's zlib module允許壓縮任意的字節塊,並且the pigz man page描述了用於已經壓縮和輸出格式並行化的系統。

如果你真的需要並行壓縮,它應該是可能實現pigz相當於使用zlib壓縮塊包裹在multiprocessing.dummy.Pool.imapmultiprocessing.dummymultiprocessing API的線程支持的版本,這樣你就不會招致巨大的成本IPC向工作人員發送大塊數據)和並行化壓縮。由於zlib是在CPU綁定工作期間發佈GIL的少數內置模塊之一,因此您可能會從基於線程的並行性中獲益。請注意,在實踐中,當壓縮級別沒有達到那麼高的時候,I/O通常與實際的壓縮相似(在數量級左右)成本;如果您的數據源無法以比壓縮更快的速度提供線程,那麼並行化您將無法獲得太多收益。

+0

您不必將塊傳送給工人。讓每個工作人員從文件中讀取它自己的塊。或者在UNIX上,您可以在創建池之前爲輸入*創建內存映射文件。然後,操作系統的虛擬內存系統將完成大部分重要工作,以將輸入文件的頁面保存在內存中。 –

+0

@RolandSmith:的確如此。對於所有的事情我都是'mmap'的忠實粉絲,看起來'zlib.compress'是緩衝協議友好的(也就是說,它可以從'mmap'的'memoryview'中讀取以避免複製數據)。你仍然需要'imap'來協調工作人員拉塊並組織輸出(因爲壓縮塊的大小不能被提前猜出,所以你也可以將寫操作序列化)。 – ShadowRanger

+0

至於協調,我只是爲每個128 kB塊的開始和「imap」創建一個字節偏移量列表。至於輸出,我可能會將每個壓縮塊寫入一個臨時輸出文件並稍後連接它們。或者也可以試試'mmap'。將它傳遞迴父進程*感覺不是最理想的。 –

2

您可以使用flush()操作與Z_SYNC_FLUSH完成最後的放氣塊,並結束它在字節邊界上。只要連接的最後一個用Z_FINISH(這是flush()的默認值)刷新,您可以將它們連接在一起以生成有效的deflate流。

你也想計算並行的CRC-32(無論是zip或gzip的 - 我覺得你真的是並行gzip壓縮)。 Python不提供zlib的crc32_combine()函數的接口。但是,您可以從zlib複製代碼並將其轉換爲Python。它的速度足夠快,因爲它不需要經常運行。你也可以預先建立你需要的表格來加快速度,甚至可以預先建立一個固定塊長度的矩陣。