Zstd: Die Zstd-Multithread-Ausgabe kann von der Anzahl der Threads abhängen

Erstellt am 25. Sept. 2020  ·  3Kommentare  ·  Quelle: facebook/zstd

Beschreibe den Fehler
Wie von @animalize in Ausgabe #2238 berichtet:

Bei Verwendung der Direktive ZSTD_e_end und einer Ausgabepuffergröße >= ZSTD_compressBound() wird die Jobnummer von der Funktion ZSTDMT_computeNbJobs() berechnet. Diese Funktion erzeugt je nach nbWorkers eine unterschiedliche Anzahl von Jobs:

https://github.com/facebook/zstd/blob/b706286adbba78006a47ef92df0ad7a785666b6/lib/compress/zstdmt_compress.c#L1243 -L1255

Erwartetes Verhalten
Die Ausgabe der ZSTD-Multithread-Komprimierung muss unabhängig von der Anzahl der Threads sein.

Fix

  • [ ] Macht ZSTDMT_computeNbJobs() unabhängig von nbWorkers .
  • [ ] Fügen Sie einen Fuzz-Test hinzu, der überprüft, ob die Ausgabe von multithreaded zstd immer unabhängig von der Anzahl der Threads ist.

Problemumgehung
Wenn Sie diesen Fehler umgehen müssen, starten Sie Ihren Streaming-Job nicht mit ZSTD_e_end. Übergeben Sie mindestens ein Byte der Eingabe mit ZSTD_e_continue, bevor Sie ZSTD_e_end aufrufen, oder stellen Sie sicher, dass Ihr Ausgabepuffer < ZSTD_compressBound(inputSize) .

bug

Hilfreichster Kommentar

Dies könnte weniger störend sein als der Versuch, den Single-Pass-MT-Kompressor anzupassen,
die nie dafür ausgelegt war, diese Garantie zu bieten.

Ja, das ist wahrscheinlich einfacher. Ich hatte vergessen, dass alle Jobs im Single Pass MT-Kompressor auf einmal gestartet werden mussten.

Ich wollte einmal vorschlagen, eine ZSTD_compressStream3()-Funktion hinzuzufügen, die bei Multithread-Komprimierung immer blockiert.

Im Allgemeinen sollte die Art und Weise, wie Leute Streaming-Kompressionsschleifen schreiben, nicht allzu unbequem sein, keinen maximalen Fortschritt zu erzielen. Wenn wir so etwas hinzufügen würden, wäre keine neue API erforderlich. Wir müssten wahrscheinlich nur einen Komprimierungsparameter hinzufügen, um ihn zu steuern. Aber ich sehe derzeit keinen großen Bedarf dafür.

Alle 3 Kommentare

Es ist eine Abkürzung zu sagen, dass das Ergebnis von Multithreaded zstd nicht von der Anzahl der Threads abhängt.

Tatsächlich ist die unterstützte Funktion, dass das Ergebnis von _streaming_ multithreaded zstd nicht von der Anzahl der Threads abhängt
(und das wird von der zstd CLI verwendet).

Diese Definition ermöglicht es, eine andere mögliche Lösung in Betracht zu ziehen:
Verwenden Sie nicht die One-Pass-Verknüpfung für ZSTD_e_end wenn nbWorkers >= 1 ,
da es die Delegierung an den One-Pass-Modus ist, die dieses Problem auslöst.

Dies könnte weniger störend sein als der Versuch, den Single-Pass-MT-Kompressor anzupassen,
die nie dafür ausgelegt war, diese Garantie zu bieten.

Ein weiterer (potenziell positiver) Nebeneffekt besteht darin, dass die Streaming-Multithread-Komprimierung _immer_ blockierungsfrei ist, da sie nicht mehr an den (blockierenden) Single-Pass-Modus delegieren würde.
_edit_ : Verschrotten, das nicht länger an den Single-Pass-Modus delegiert, garantiert keine Nicht-Blockierung, da sich der MT-API-Vertrag nach Erhalt der Anweisung ZSTD_e_flush und ZSTD_e_end von minimalem Vorwärtsfortschritt auf ändert maximalen Fortschritt.

Ein weiterer (möglicherweise positiver) Nebeneffekt besteht darin, dass die Streaming-Multithread-Komprimierung immer blockierungsfrei ist, da sie nicht mehr an den Blockierungsmodus delegieren würde.

Ich wollte einmal vorschlagen, eine ZSTD_compressStream3() Funktion hinzuzufügen, die bei Multithread-Komprimierung immer blockiert.

Wenn der Anrufer den Fortschritt der Nichtblockierung ständig überprüft, ist dies sehr umständlich .

edit : Gerade gefunden, die Überprüfung des Fortschritts ist nicht sehr umständlich:

do {
    zstd_ret = ZSTD_compressStream2(self->cctx, &out, &in, ZSTD_e_continue);
} while (out.pos != out.size && in.pos != in.size && !ZSTD_isError(zstd_ret));

Aber es ist besser, ein immer blockierendes ZSTD_compressStream3() , es kann etwas schneller sein, IMO müssen viele Programmierer den Fortschritt der Komprimierung nicht abrufen.

Dies könnte weniger störend sein als der Versuch, den Single-Pass-MT-Kompressor anzupassen,
die nie dafür ausgelegt war, diese Garantie zu bieten.

Ja, das ist wahrscheinlich einfacher. Ich hatte vergessen, dass alle Jobs im Single Pass MT-Kompressor auf einmal gestartet werden mussten.

Ich wollte einmal vorschlagen, eine ZSTD_compressStream3()-Funktion hinzuzufügen, die bei Multithread-Komprimierung immer blockiert.

Im Allgemeinen sollte die Art und Weise, wie Leute Streaming-Kompressionsschleifen schreiben, nicht allzu unbequem sein, keinen maximalen Fortschritt zu erzielen. Wenn wir so etwas hinzufügen würden, wäre keine neue API erforderlich. Wir müssten wahrscheinlich nur einen Komprimierungsparameter hinzufügen, um ihn zu steuern. Aber ich sehe derzeit keinen großen Bedarf dafür.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen