2010-11-05 6 views
4

J'ai plusieurs commandes que je voudrais exécuter en parallèle. Les commandes sont presque identiques. On peut s'attendre à ce qu'ils prennent à peu près le même temps et puissent fonctionner de manière complètement indépendante. Ils peuvent ressembler à:Utilisation de make pour exécuter des tâches indépendantes en parallèle

command -n 1 > log.1 
command -n 2 > log.2 
command -n 3 > log.3 
... 
command -n 4096 > log.4096 

je pouvais lancer tous en parallèle dans un script shell, mais le système essaieraient de charger plus que strictement nécessaire pour maintenir la CPU (s) occupé (chaque tâche prend 100% d'un noyau jusqu'à ce qu'il ait fini). Cela causerait le thrash du disque et rendrait l'ensemble plus lent qu'une approche moins gourmande à l'exécution.

La meilleure approche est probablement de garder environ n tâches en cours d'exécution, où n est le nombre de cœurs disponibles. Je souhaite ne pas réinventer la roue. Ce problème a déjà été résolu dans le programme Unix make (lorsqu'il est utilisé avec l'option -j n). Je me demandais s'il était possible d'écrire des règles de Makefile génériques pour ce qui précède, de manière à éviter le Makefile taille linéaire qui ressemblerait à ceci:

all: log.1 log.2 ... 
log.1: 
     command -n 1 > log.1 
log.2: 
     command -n 2 > log.2 
... 

Si la meilleure solution est de ne pas utiliser make mais un autre programme/utilitaire, je suis ouvert à cela tant que les dépendances sont raisonnables (make était très bon à cet égard).

Répondre

3

Voir pattern rules

Une autre façon, si c'est la seule raison pour laquelle vous avez besoin make, est d'utiliser -n et -P options xargs.

+0

echo '{1..1024} | xargs -n 1 -P 4 echo' donner '1 3 2 5 4 ...' (bash 3) semble sur ce que je veux. Je n'y ai pas pensé à ce moment-là, mais je peux aussi écrire «n» des scripts séquentiels pour les tranches «1», «N/n», «N/N + 1», «N2», etc. Tant que les tranches sont moyennes en même temps (ce n'est pas une donnée). –

3

D'abord la partie facile. Comme le souligne Roman Cheplyaka sur, les règles de modèle sont très utiles:

LOGS = log.1 log.2 ... log.4096 
all: $(LOGS) 

log.%: 
    command -n $* > log.$* 

La partie la plus délicate est la création de cette liste, LOGS. Make n'est pas très bon pour gérer les nombres. Le meilleur moyen est probablement d'appeler le shell. (Vous devrez peut-être modifier ce script pour votre script shell shell-- n'est pas mon sujet le plus fort.)

NUM_LOGS = 4096 

LOGS = $(shell for ((i=1 ; i<=$(NUM_LOGS) ; ++i)) ; do echo log.$$i ; done) 
+0

Bonjour, merci pour votre aide. Bash 3 a le motif '{1..1024}' qui peut probablement être utilisé pour la seconde partie. –

3

xargs -P est la voie « standard » de le faire. Notez qu'en fonction des E/S de disque, vous pouvez limiter les broches aux coeurs. Si vous voulez limiter aux cœurs, notez la nouvelle commande nproc dans les coreutils récents.

+0

Dans mon cas, je pouvais adapter toutes les entrées et les sorties des tâches dans un disque virtuel si j'en avais besoin, mais merci de me présenter la notion de "broche". –

4

Voici le code shell plus portable qui ne dépend pas de l'expansion du corset:

JOURNAUX: = $ (shell suivants 1 1024)

Notez l'utilisation: = pour définir un plus variable efficace: la "saveur" simplement étendue.

Questions connexes