2017-03-17 1 views
3

Big file compression with python gibt ein sehr schönes Beispiel, wie z. bz2 um einen sehr großen Satz von Dateien (oder eine große Datei) rein in Python zu komprimieren.Wie erreicht man parallele Gzip-Komprimierung mit Python?

pigz sagt, dass Sie besser durch die parallele Komprimierung ausnutzen können. Nach meinem Wissen (und Google-Suche) kann ich insofern kein Python-Pendant zu reinem Python-Code finden.

Gibt es eine parallele Python-Implementierung für pigz oder gleichwertig?

+0

Die Komprimierungsmodule aus der Standardbibliothek sind nicht * pure python *. Wenn Sie sich diese ansehen, werden Sie feststellen, dass sie Schnittstellen zu gemeinsam genutzten Bibliotheken sind (die in C geschrieben sind). –

+2

Und es ist wahrscheinlich Zeit, 'gzip' in Rente zu gehen. Die neue 'zstd'-Komprimierung ist [im Allgemeinen schneller] (http://rsmith.home.xs4all.nl/miscellaneous/evaluating-zstandard-compression.html) als gzip und liefert kleinere komprimierte Dateien. –

+1

@RolandSmith: Natürlich, Es hat auch keine Python-Schnittstelle. Es scheint schneller als 'gzip', aber es gibt viele Optionen für" schneller komprimieren ". 'gzip' haftet zumindest teilweise dank Kompatibilitätsproblemen; Sie können es auf Systemen mit über 10 Jahre alter Hardware/Software dekomprimieren, und es ist wahrscheinlich standardmäßig installiert ('bz2' ist fast so weit verbreitet,' xz' kommt dorthin). Für die Verteilung von Daten an viele Parteien sind Portabilität und Komprimierungsrate wichtiger als Geschwindigkeit. Bei der transienten Kompression schlägt die Geschwindigkeit oft das Kompressionsverhältnis, so dass 'lz4' oder' lzo' 'zstd' schlagen könnten. – ShadowRanger

Antwort

4

Ich kenne keine pigz Schnittstelle für Python off-Hand, aber es ist nicht so schwer zu schreiben, wenn Sie es wirklich brauchen. Python's zlib module ermöglicht das Komprimieren beliebiger Bytes, und the pigz man page beschreibt das System für die Parallelisierung der Komprimierung und das Ausgabeformat bereits.

Wenn Sie wirklich parallele Kompression benötigen, soll es möglich sein, eine pigz gleichwertig mit zlib zu implementieren Brocken in multiprocessing.dummy.Pool.imap gewickelt zu komprimieren (multiprocessing.dummy die Thread-backed-Version des multiprocessing API, so dass Sie nicht massiv IPC Kosten entstünden Senden von Blöcken an und von den Arbeitern), um die Komprimierung parallel zu machen. Da zlib eines der wenigen integrierten Module ist, das die GIL während der CPU-gebundenen Arbeit freigibt, könnten Sie tatsächlich von der Thread-basierten Parallelität profitieren.

Beachten Sie, dass in der Praxis, wenn der Komprimierungsgrad nicht so hoch ist, I/O ist oft ähnlich (in der Größenordnung oder so) Kosten für die tatsächliche zlib Kompression; Wenn Ihre Datenquelle die Threads nicht schneller füttern kann, als sie komprimieren, werden Sie durch die Parallelisierung nicht viel gewinnen.

+0

Sie müssen die Stücke nicht an die Arbeiter schicken. Lassen Sie jeden Arbeiter seine eigenen Stücke aus der Datei lesen. Oder Sie können unter UNIX eine Memory-Mapped-Datei für die Eingabe * erstellen *, bevor Sie den Pool erstellen. Das virtuelle Speichersystem des Betriebssystems wird dann den größten Teil der Last aufwenden, um die Seiten der Eingabedatei im Speicher zu halten. –

+0

@RolandSmith: True. Ich bin ein großer Fan von 'mmap' für all die Dinge, und es sieht so aus, als ob' zlib.compress' Pufferprotokoll-freundlich ist (das heißt, es kann von einer 'Speicheransicht' einer' mmap' lesen, um das Kopieren der Daten zu vermeiden). Sie sollten immer noch "imap" haben, um die Arbeiter zu koordinieren, die Blöcke ziehen und die Ausgabe organisieren (da die Größe des komprimierten Blocks nicht im Voraus erraten werden kann, können Sie auch die Schreiboperationen serialisieren). – ShadowRanger

+0

Wie für die Koordination, würde ich nur eine Liste von Byte-Offsets für den Start jedes 128 kB-Block und "Imap" darüber erstellen. Was die Ausgabe betrifft, würde ich wahrscheinlich jeden komprimierten Block in eine temporäre Ausgabedatei schreiben und sie später verketten. Oder vielleicht versuchen Sie auch 'mmap' dafür. Das Zurückgeben an den Elternprozess * fühlt sich * suboptimal an. –

2

Sie können den flush()-Vorgang mit Z_SYNC_FLUSH verwenden, um den letzten Deflate-Block zu vervollständigen und ihn auf einer Bytegrenze zu beenden. Sie können diese verketten, um einen gültigen Deflate-Stream zu erstellen, solange der letzte, den Sie verketten, mit Z_FINISH geleert wird (was der Standardwert für flush() ist).

Sie würden auch die CRC-32 parallel berechnen wollen (ob für Zip oder Gzip - ich denke, Sie meinen, parallel Gzip-Komprimierung). Python bietet keine Schnittstelle zur Funktion crc32_combine() von zlib. Sie können jedoch den Code von zlib kopieren und in Python konvertieren. Es wird schnell genug sein, da es nicht oft ausgeführt werden muss. Außerdem können Sie die Tabellen, die Sie für eine schnellere Blocklänge benötigen, vorab erstellen oder sogar eine Matrix für eine feste Blocklänge erstellen.

Verwandte Themen