J'utilise xargs
pour appeler un script python pour traiter environ 30 millions de petits fichiers. J'espère utiliser xargs
pour paralléliser le processus. La commande que j'utilise est:
find ./data -name "*.json" -print0 |
xargs -0 -I{} -P 40 python Convert.py {} > log.txt
Fondamentalement, Convert.py
lira dans un petit fichier json (4 Ko), effectuera un certain traitement et écrit dans un autre fichier 4 Ko. Je cours sur un serveur avec 40 cœurs CPU. Et aucun autre processus gourmand en CPU n'est en cours d'exécution sur ce serveur.
En surveillant htop (btw, existe-t-il un autre bon moyen de surveiller les performances du processeur?), Je trouve que ce -P 40
n'est pas aussi rapide que prévu. Parfois, tous les cœurs gèlent et diminuent presque à zéro pendant 3-4 secondes, puis récupèrent à 60-70%. Ensuite, j'essaie de diminuer le nombre de processus parallèles à -P 20-30
, mais ce n'est toujours pas très rapide. Le comportement idéal devrait être une accélération linéaire. Des suggestions pour l'utilisation parallèle de xargs?
la source
xargs -P
et>
s'ouvre pour des conditions de course en raison du problème de demi-ligne gnu.org/software/parallel/… Utiliser GNU Parallel à la place n'aura pas ce problème.Réponses:
Je serais prêt à parier que votre problème est le python . Vous n'avez pas dit quel type de traitement est effectué sur chaque fichier, mais en supposant que vous ne faites que le traitement en mémoire des données, le temps d'exécution sera dominé par le démarrage de 30 millions de machines virtuelles python (interprètes).
Si vous pouvez restructurer votre programme python pour prendre une liste de fichiers, au lieu d'un seul, vous obtiendrez une énorme amélioration des performances. Vous pouvez alors toujours utiliser xargs pour améliorer encore les performances. Par exemple, 40 processus, chacun traitant 1000 fichiers:
Cela ne veut pas dire que python est un langage mauvais / lent; il n'est tout simplement pas optimisé pour le temps de démarrage. Vous verrez cela avec n'importe quel langage basé sur une machine virtuelle ou interprété. Java, par exemple, serait encore pire. Si votre programme était écrit en C, il y aurait toujours un coût de démarrage d'un processus de système d'exploitation distinct pour gérer chaque fichier, mais ce serait beaucoup moins.
De là, vous pouvez jouer avec
-P
pour voir si vous pouvez accélérer un peu plus, peut-être en augmentant le nombre de processus pour profiter des processeurs inactifs pendant la lecture / l'écriture des données.la source
Considérons donc tout d'abord les contraintes:
Quelle est la contrainte sur chaque travail? Si c'est des E / S, vous pouvez probablement vous en sortir avec plusieurs tâches par cœur de processeur jusqu'à ce que vous atteigniez la limite des E / S, mais si elles sont gourmandes en ressources processeur, cela va être pire qu'inutile d'exécuter plus de tâches simultanément que vous n'avez de cœurs de processeur.
Ma compréhension de ces choses est que GNU Parallel vous donnerait un meilleur contrôle sur la file d'attente des travaux, etc.
Voir GNU parallèle vs & (je veux dire arrière-plan) vs xargs -P pour une explication plus détaillée de la différence entre les deux.
la source
Comme d'autres l'ont dit, vérifiez si vous êtes lié aux E / S. De plus, la page de manuel de xargs suggère d'utiliser
-n
avec-P
, vous ne mentionnez pas le nombre deConvert.py
processus que vous voyez fonctionner en parallèle.Comme suggestion, si vous êtes lié aux E / S, vous pouvez essayer d'utiliser un périphérique de bloc SSD, ou essayer de faire le traitement dans un tmpfs (bien sûr, dans ce cas, vous devriez vérifier suffisamment de mémoire, en évitant le swap dû à tmpfs pression (je pense), et les frais généraux de la copie des données à elle en premier lieu).
la source