8 Stimmen

Wie bringe ich Java dazu, meinen Multi-Core-Prozessor mit GZIPInputStream zu nutzen?

Ich verwende einen GZIPInputStream in meinem Programm, und ich weiß, dass die Leistung verbessert werden würde, wenn ich Java mein Programm parallel ausführen lassen könnte.

Gibt es generell eine Befehlszeilenoption für die Standard-VM, die auf vielen Kernen läuft? Im Moment läuft sie nur auf einem.

Gracias.

bearbeiten

Ich verwende Java SE 6 Update 17 unter Windows XP.

Würde es helfen, den GZIPInputStream explizit in einen separaten Thread zu legen? Nein! Legen Sie den GZIPInputStream nicht auf einen separaten Thread! Keine Multithread-E/A!

Bearbeiten 2

Ich vermute, dass E/A der Engpass ist, da ich auf derselben Festplatte lese und schreibe...

Gibt es jedoch eine Möglichkeit, GZIPInputStream generell schneller zu machen? Oder einen Ersatz für GZIPInputStream, der parallel läuft?

Bearbeiten 3 Verwendeter Codeschnipsel:

GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(INPUT_FILENAME));
DataInputStream in = new DataInputStream(new BufferedInputStream(gzip));

16voto

Uri Punkte 86472

AFAIK die Aktion des Lesens von diesem Strom ist Single-Thread, so dass mehrere CPUs werden Ihnen nicht helfen, wenn Sie eine Datei lesen.

Sie könnten jedoch mehrere Threads haben, die jeweils eine andere Datei entpacken.

Abgesehen davon ist das Entpacken heutzutage nicht besonders rechenintensiv, man wird eher durch die IO-Kosten blockiert (z. B. wenn man zwei sehr große Dateien in zwei verschiedenen Bereichen der Festplatte liest).

Allgemeiner ausgedrückt (wenn man davon ausgeht, dass dies eine Frage von jemandem ist, der neu in Java ist), erledigt Java keine Dinge parallel für Sie. Sie müssen Threads verwenden, um dem Programm mitzuteilen, welche Arbeitseinheiten Sie ausführen wollen und wie die Synchronisierung zwischen ihnen erfolgen soll. Java wird (mit Hilfe des Betriebssystems) in der Regel so viele Kerne verwenden, wie ihm zur Verfügung stehen, und wird auch Threads auf demselben Kern austauschen, wenn es mehr Threads als Kerne gibt (was normalerweise der Fall ist).

6voto

George Punkte 71

PIGZ = Parallel Implementation of GZip (Parallele Implementierung von GZip) ist ein voll funktionsfähiger Ersatz für gzip, der mehrere Prozessoren und mehrere Kerne bei der Komprimierung von Daten optimal ausnutzt. http://www.zlib.net/pigz/ Es ist noch nicht Java - gibt es Interessenten? Natürlich braucht die Welt es in Java.

Manchmal ist die Komprimierung oder Dekomprimierung ein großer CPU-Verbraucher, obwohl sie dazu beiträgt, dass die E/A nicht der Flaschenhals ist.

Siehe auch Dataseries (C++) von HP Labs. PIGZ parallelisiert nur die Komprimierung, während Dataseries die Ausgabe in große komprimierte Blöcke aufteilt, die parallel dekomprimiert werden können. Hat auch eine Reihe anderer Funktionen.

2voto

Sam Barnum Punkte 10220

Wickeln Sie Ihre GZIP-Streams in gepufferte Streams ein, das sollte Ihnen eine deutliche Leistungssteigerung bringen.

OutputStream out = new BufferedOutputStream(
    new GZIPOutputStream(
        new FileOutputStream(myFile)
    )
)

Dasselbe gilt für den Eingangsstrom. Die Verwendung der gepufferten Ein- und Ausgabeströme verringert die Anzahl der Lesevorgänge auf der Festplatte.

2voto

Carl Smotricz Punkte 64366

Ich sehe keine Antwort auf die Frage andere Verarbeitung Ihres Programms.

Wenn Sie nur eine Datei entpacken, ist es besser, einfach die Befehlszeile zu verwenden gunzip Tool; aber wahrscheinlich findet eine Verarbeitung der Dateien statt, die Sie aus diesem Stream abrufen.

Wenn Sie etwas extrahieren, das in angemessen großen Brocken vorliegt, dann sollte die Verarbeitung dieser Brocken in einem vom Entpacken getrennten Thread erfolgen.

Sie könnten manuell einen Thread für jeden großen String oder einen anderen Datenblock starten, aber seit Java 1.6 oder so sind Sie besser dran mit einer der schicken neuen Klassen in java.util.concurrent wie zum Beispiel ein ThreadPoolExecutor .


Update

Aus der Frage und den anderen Kommentaren geht für mich nicht klar hervor, ob Sie wirklich nur Dateien mit Java extrahieren. Wenn Sie wirklich glauben, dass Sie versuchen sollten, sich mit gunzip dann können Sie wahrscheinlich etwas Leistung gewinnen, indem Sie große Puffer verwenden; d.h. arbeiten Sie mit einem Puffer von, sagen wir, 10 MB (binär, nicht dezimal! - 1048576), füllen Sie diesen in einem einzigen Schluck und schreiben Sie ihn ebenfalls auf die Festplatte. Das gibt Ihrem Betriebssystem die Möglichkeit, den Speicherplatz auf mittlerer Ebene zu planen, und Sie benötigen auch weniger Systemaufrufe.

0voto

Die Komprimierung scheint ein schwieriger Fall für die Parallelisierung zu sein, weil die vom Kompressor ausgegebenen Bytes eine nicht-triviale Funktion der vorherigen W Bytes der Eingabe sind, wobei W die Fenstergröße ist. Sie können eine Datei natürlich in Teile zerlegen und für jeden Teil unabhängige Kompressionsströme erstellen, die in eigenen Threads laufen. Möglicherweise müssen Sie einige Komprimierungsmetadaten beibehalten, damit der Dekomprimierer weiß, wie er die Datei wieder zusammensetzen kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X