Supposons que je veuille trouver toutes les correspondances dans un fichier texte compressé:
$ gzcat file.txt.gz | pv --rate -i 5 | grep some-pattern
pv --rate
utilisé ici pour mesurer le débit des tuyaux. Sur ma machine, c'est environ 420Mb / s (après décompression).
Maintenant j'essaye de faire du grep parallèle en utilisant GNU parallel.
$ gzcat documents.json.gz | pv --rate -i 5 | parallel --pipe -j4 --round-robin grep some-pattern
Le débit est maintenant abaissé à ~ 260 Mo / s. Et ce qui est le plus intéressant parallel
, c'est d'utiliser beaucoup de CPU. Plus que des grep
processus (mais moins que gzcat
).
EDIT 1 : J'ai essayé différentes tailles de blocs ( --block
), ainsi que différentes valeurs pour -N
/ -L
options. Rien ne m'aide à ce stade.
Qu'est-ce que je fais mal?
la source
--pipe
est inefficace? Je veux dire que c'est une sorte de problème fondamental ou plus de mise en œuvre spécifique.--pipe
chaque octet unique doit passer par le processus unique, qui doit faire un peu de traitement sur chaque octet. Avec la--pipepart
plupart des octets ne sont jamais vus par le processus central: ils sont traités par des travaux générés. Comme ce sont assez peu de lignes qui constituent le goulot d'étranglement--pipe
, j'accueillerais un codeur C / C ++ qui réécrirait la partie qui serait ensuite exécutée pour les personnes ayant un compilateur C sur leur chemin.grep est très efficace - cela n'a aucun sens de l'exécuter en parallèle. Dans votre commande, seule la décompression a besoin de plus de cpu, mais cela ne peut pas être mis en parallèle.
Le fractionnement des entrées par parallèle nécessite plus de CPU que d'obtenir des lignes correspondantes par grep.
Changement de situation si vous souhaitez utiliser au lieu de grep quelque chose qui nécessite beaucoup plus de cpu pour chaque ligne - alors parallèle aurait plus de sens.
Si vous souhaitez accélérer cette opération - regardez où se trouvent les goulots d'étranglement - c'est probablement la décompression (puis aide à utiliser un autre outil de décompression ou un meilleur processeur) ou - la lecture à partir du disque (puis aide à utiliser un autre outil de décompression ou un meilleur système de disque).
D'après mon expérience - il est parfois préférable d'utiliser lzma (-2 par exemple) pour compresser / décompresser des fichiers - il a une compression plus élevée que gzip, donc beaucoup moins de données doivent être lues sur le disque et la vitesse est comparable.
la source
La décompression est ici le goulot d'étranglement. Si la décompression n'est pas parallélisée en interne, vous n'y arriverez pas par vous-même. Si vous avez plus d'un travail comme celui-là, alors bien sûr, lancez-les en parallèle, mais votre pipeline en lui-même est difficile à paralléliser. La division d'un flux en flux parallèles n'en vaut presque jamais la peine et peut être très pénible avec la synchronisation et la fusion. Parfois, vous devez simplement accepter que plusieurs cœurs ne vous aideront pas pour chaque tâche que vous exécutez.
En général, la parallélisation en shell doit se faire principalement au niveau de processus indépendants.
la source
parallel
. Je suis d'accord que c'est certainement dans le premier cas (sans parallèle), mais dans le second (avec parallèle) le goulot d'étranglement est du côté parallèle. Cela découle de l'observation que le débit diminue de manière significative, tel que mesuré parpv
. Si le goulot d'étranglement est en décompression, le débit ne changera pas ce que vous ajoutez au pipeline. C'est une définition très intuitive du débit, je suppose - la chose qui limite le plus le débit.parallel
peut être écrit sur son pipe. Dans ce cas, la plupart desgrep
processus attendent simplement d'en avoir plus, tout enparallel
travaillant 24 heures sur 24 pour multiplexer les blocs en plusieurs canaux (qui sont des opérations d'E / S supplémentaires et peuvent même bloquer la décompression si le tampon est plein). Avez-vous également essayé de jouer avec le--block
paramètre? Par défaut,1M
jusqu'à ce qu'un grep obtienne des1M
données, le reste est presque certainement déjà terminé. Nous revenons donc au fait que cela n'a aucun sens de paralléliser cela.-N
/-L
options. Il semble que les options par défaut soient très proches de l'optimum local que j'ai connu :)pv
(avectime
). De cette façon, vous pouvez voir sipv
lui-même le ralentit. Si c'est le cas, laparallel
copie de données dans des tuyaux est certainement un surcoût supplémentaire. Et dans tous les cas, je suis sûr quegrep
c'est presque en temps réel dans ce cas, surtout si le modèle est une chaîne simple sans beaucoup de retour en arrière. De plus,parallel
entrelacera et gâchera lesgrep
sorties.pv
lui - même ne cause pas le problème, merci pour les conseils.