Considérez le scénario suivant. J'ai deux programmes A et B. Le programme A sort des lignes de chaînes standard tandis que le programme B traite les lignes de stdin. La façon d'utiliser ces deux programmes est bien sûr:
foo @ bar: ~ $ A | B
Maintenant, j'ai remarqué que cela ne mange qu'un seul noyau; je me demande donc:
Les programmes A et B partagent-ils les mêmes ressources de calcul? Si oui, existe-t-il un moyen d'exécuter A et B simultanément?
Une autre chose que j'ai remarquée est que A s'exécute beaucoup plus rapidement que B, donc je me demande si pourrait en quelque sorte exécuter plus de programmes B et les laisser traiter les lignes que A sort en parallèle.
Autrement dit, A afficherait ses lignes, et il y aurait N instances de programmes B qui liraient ces lignes (celui qui les lirait en premier) les traiteraient et les sortiraient sur stdout.
Donc ma dernière question est:
Existe-t-il un moyen de diriger la sortie vers A parmi plusieurs processus B sans avoir à prendre en compte les conditions de concurrence et les autres incohérences qui pourraient survenir?
la source
A | B | C
soit parallèle comme dans des processus séparés, en raison de la nature des tuyaux (B doit attendre la sortie de A, C doit attendre la sortie de B), il peut toujours être linéaire dans certains cas. Cela dépend entièrement du type de sortie qu'ils produisent. Il n'y a pas beaucoup de cas où l'exécution multipleB
aiderait beaucoup, il est tout à fait possible que l'exemple de wc parallèle soit plus lent que normalwc
car le fractionnement peut prendre plus de ressources que de compter les lignes normalement. Utilisez avec précaution.Réponses:
Un problème
split --filter
est que la sortie peut être mélangée, donc vous obtenez une demi-ligne du processus 1 suivie d'une demi-ligne du processus 2.GNU Parallel garantit qu'il n'y aura pas de confusion.
Supposez donc que vous voulez faire:
Mais ce B est terriblement lent, et donc vous voulez paralléliser cela. Ensuite, vous pouvez faire:
GNU Parallel se divise par défaut sur \ n et une taille de bloc de 1 Mo. Cela peut être ajusté avec --recend et --block.
Vous pouvez trouver plus d'informations sur GNU Parallel sur: http://www.gnu.org/s/parallel/
Vous pouvez installer GNU Parallel en seulement 10 secondes avec:
Regardez la vidéo d'introduction sur http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
la source
--block-size
dépendra de la quantité de RAM et de la vitesse à laquelle vous pourrez en démarrer une nouvelleB
. Dans votre situation, j'utiliserais--block 100M
et verrais comment cela a fonctionné.sh
- est excellente. Le problème consiste à le passer à sh: télécharger et exécuter du code exécutable à partir d'un site . Attention, je suis peut-être trop paranoïaque, car on pourrait objecter qu'un RPM ou un DEB sur mesure est fondamentalement la même chose, et même publier le code sur une page à copier et coller entraînerait des personnes aveugles en tous cas.Lorsque vous écrivez
A | B
, les deux processus s'exécutent déjà en parallèle. Si vous les voyez comme n'utilisant qu'un seul cœur, c'est probablement à cause des paramètres d'affinité du processeur (peut-être qu'il existe un outil pour générer un processus avec une affinité différente) ou parce qu'un processus ne suffit pas pour contenir un cœur entier et le système " préfère "ne pas étendre l'informatique.Pour exécuter plusieurs B avec un A, vous avez besoin d'un outil tel que
split
l'--filter
option:Cependant, cela risque de perturber l'ordre des lignes dans la sortie, car les travaux B ne s'exécuteront pas tous à la même vitesse. S'il s'agit d'un problème, vous devrez peut-être rediriger la sortie B i-ème vers un fichier intermédiaire et les assembler à la fin à l'aide de
cat
. Ceci, à son tour, peut nécessiter un espace disque considérable.D' autres options existent (par exemple , vous pouvez limiter chaque instance de B à une seule sortie en mémoire tampon ligne, attendez jusqu'à ce qu'un tout « rond » de B est terminée, lancez l'équivalent d'une réduire à
split
« s carte , etcat
la sortie temporaire ensemble), avec différents niveaux d'efficacité. L'option 'round' qui vient d'être décrite, par exemple, attendra la fin de l' instance la plus lente de B , elle dépendra donc grandement de la mise en mémoire tampon disponible pour B;[m]buffer
pourrait aider, ou non, selon les opérations.Exemples
Générez les 1000 premiers nombres et comptez les lignes en parallèle:
Si nous devions "marquer" les lignes, nous verrions que chaque première ligne est envoyée au processus # 1, chaque cinquième ligne au processus # 5 et ainsi de suite. De plus, dans le temps qu'il faut
split
pour engendrer le second processus, le premier est déjà un bon chemin dans son quota:Lors de l'exécution sur une machine à 2 cœurs
seq
,split
et leswc
processus partagent les cœurs; mais en y regardant de plus près, le système laisse les deux premiers processus sur CPU0 et divise CPU1 entre les processus de travail:Notez surtout que
split
consomme une quantité considérable de CPU. Cela diminuera proportionnellement aux besoins de A; c'est-à-dire que si A est un processus plus lourd queseq
, la surcharge relative desplit
diminuera. Mais si A est un processus très léger et B est assez rapide (de sorte que vous n'avez pas besoin de plus de 2-3 B pour rester avec A), la parallélisation avecsplit
(ou les tuyaux en général) pourrait ne pas en valoir la peine.la source
split
--filter
option manquante? Sur mon Ubuntu 12.04-LTS ("wheezy / sid"), il est là, et mes exemples fonctionnent. Auriez-vous pu en installer un autresplit
que celui de GNU coreutils?