Zstd: La sortie multithread de Zstd peut dépendre du nombre de threads

Créé le 25 sept. 2020  ·  3Commentaires  ·  Source: facebook/zstd

Décrivez le bogue
Tel que rapporté par @animalize dans le numéro #2238 :

Lors de l'utilisation de la directive de fin ZSTD_e_end et de la taille du tampon de sortie >= ZSTD_compressBound(), le numéro de tâche est calculé par la fonction ZSTDMT_computeNbJobs(). Cette fonction produit un nombre différent de jobs en fonction de nbWorkers :

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

Comportement prévisible
La sortie de la compression multithread zstd doit être indépendante du nombre de threads.

Réparer

  • [ ] Rendre ZSTDMT_computeNbJobs() indépendant de nbWorkers .
  • [ ] Ajout d'un test fuzz qui vérifie que la sortie de zstd multithread est toujours indépendante du nombre de threads.

solution de contournement
Si vous devez contourner ce bogue, ne démarrez pas votre tâche de streaming avec ZSTD_e_end. Passez au moins un octet d'entrée avec ZSTD_e_continue avant d'appeler ZSTD_e_end, ou assurez-vous que votre tampon de sortie est de < ZSTD_compressBound(inputSize) .

bug

Commentaire le plus utile

Cela pourrait être moins perturbant que d'essayer d'adapter le compresseur MT à un seul passage,
qui n'a jamais été conçu pour offrir cette garantie.

Oui, c'est probablement plus facile. J'avais oublié que tous les travaux du compresseur MT à un seul passage devaient être lancés en même temps.

J'ai une fois voulu proposer d'ajouter une fonction ZSTD_compressStream3(), qui bloque toujours en compression multithread.

Généralement, la façon dont les gens écrivent des boucles de compression de streaming, il ne devrait pas être très gênant de ne pas progresser au maximum. Si nous devions ajouter quelque chose comme ça, cela ne nécessiterait pas une nouvelle API. Nous aurions probablement juste besoin d'ajouter un paramètre de compression pour le contrôler. Mais, je n'en vois pas actuellement un grand besoin.

Tous les 3 commentaires

C'est un raccourci pour dire que le résultat de zstd multithread ne dépend pas du nb de threads.

En fait, la fonctionnalité prise en charge est que le résultat de _streaming_ multithread zstd ne dépend pas du nb de threads
(et c'est ce qui est utilisé par la CLI zstd ).

Cette définition permet d'envisager une autre solution potentielle :
n'utilisez pas le raccourci en un seul passage pour ZSTD_e_end lorsque nbWorkers >= 1 ,
puisque c'est la délégation au mode monopasse qui déclenche ce problème.

Cela pourrait être moins perturbant que d'essayer d'adapter le compresseur MT à un seul passage,
qui n'a jamais été conçu pour offrir cette garantie.

Un autre effet secondaire (potentiellement positif) est que cela garantirait que la compression multithread en streaming est _toujours_ non bloquante, car elle ne déléguerait plus au mode (bloquant) à passage unique.
_edit_ : supprimez cela, ne plus déléguer au mode monopasse ne garantit pas le non-blocage, car à la réception des directives ZSTD_e_flush et ZSTD_e_end , le contrat de l'API MT passe d'une progression minimale à progression maximale.

Un autre effet secondaire (potentiellement positif) est que cela garantirait que la compression multithread en streaming est toujours non bloquante, car elle ne déléguerait plus au mode de blocage.

J'ai une fois voulu proposer d'ajouter une fonction ZSTD_compressStream3() , qui bloque toujours en compression multithread.

Si l'appelant continue de vérifier la progression non bloquante, c'est très gênant .

edit : Je viens de trouver, vérifier la progression n'est pas très gênant :

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));

Mais il est préférable d'avoir un ZSTD_compressStream3() toujours bloquant, cela peut être un peu plus rapide, IMO, de nombreux utilisateurs de programmeurs n'ont pas besoin d'obtenir la progression de la compression.

Cela pourrait être moins perturbant que d'essayer d'adapter le compresseur MT à un seul passage,
qui n'a jamais été conçu pour offrir cette garantie.

Oui, c'est probablement plus facile. J'avais oublié que tous les travaux du compresseur MT à un seul passage devaient être lancés en même temps.

J'ai une fois voulu proposer d'ajouter une fonction ZSTD_compressStream3(), qui bloque toujours en compression multithread.

Généralement, la façon dont les gens écrivent des boucles de compression de streaming, il ne devrait pas être très gênant de ne pas progresser au maximum. Si nous devions ajouter quelque chose comme ça, cela ne nécessiterait pas une nouvelle API. Nous aurions probablement juste besoin d'ajouter un paramètre de compression pour le contrôler. Mais, je n'en vois pas actuellement un grand besoin.

Cette page vous a été utile?
0 / 5 - 0 notes