L'utilisation screen
avec gdb
pour déboguer les applications MPI fonctionne bien, surtout si elle xterm
n'est pas disponible ou si vous avez affaire à plus de quelques processeurs. Il y avait de nombreux pièges en cours de route avec les recherches d'accompagnement de stackoverflow, je vais donc reproduire ma solution dans son intégralité.
Tout d'abord, ajoutez du code après MPI_Init pour imprimer le PID et arrêtez le programme pour attendre que vous l'attachiez. La solution standard semble être une boucle infinie; J'ai finalement opté pour raise(SIGSTOP);
, ce qui nécessite un appel supplémentaire continue
pour s'échapper dans gdb.
}
int i, id, nid;
MPI_Comm_rank(MPI_COMM_WORLD,&id);
MPI_Comm_size(MPI_COMM_WORLD,&nid);
for (i=0; i<nid; i++) {
MPI_Barrier(MPI_COMM_WORLD);
if (i==id) {
fprintf(stderr,"PID %d rank %d\n",getpid(),id);
}
MPI_Barrier(MPI_COMM_WORLD);
}
raise(SIGSTOP);
}
Après la compilation, exécutez l'exécutable en arrière-plan et récupérez le fichier stderr. Vous pouvez ensuite grep
le fichier stderr pour un mot-clé (ici PID littéral) pour obtenir le PID et le rang de chaque processus.
MDRUN_EXE=../../Your/Path/To/bin/executable
MDRUN_ARG="-a arg1 -f file1 -e etc"
mpiexec -n 1 $MDRUN_EXE $MDRUN_ARG >> output 2>> error &
sleep 2
PIDFILE=pid.dat
grep PID error > $PIDFILE
PIDs=(`awk '{print $2}' $PIDFILE`)
RANKs=(`awk '{print $4}' $PIDFILE`)
Une session gdb peut être attachée à chaque processus avec gdb $MDRUN_EXE $PID
. Le faire dans une session d'écran permet un accès facile à n'importe quelle session gdb. -d -m
démarre l'écran en mode détaché, -S "P$RANK"
vous permet de nommer l'écran pour un accès facile plus tard, et l' -l
option de bash le démarre en mode interactif et empêche gdb de quitter immédiatement.
for i in `awk 'BEGIN {for (i=0;i<'${#PIDs[@]}';i++) {print i}}'`
do
PID=${PIDs[$i]}
RANK=${RANKs[$i]}
screen -d -m -S "P$RANK" bash -l -c "gdb $MDRUN_EXE $PID"
done
Une fois que gdb a démarré dans les écrans, vous pouvez écrire une entrée dans les écrans (afin de ne pas avoir à entrer dans chaque écran et à taper la même chose) en utilisant la -X stuff
commande screen . Une nouvelle ligne est requise à la fin de la commande. Ici, les écrans sont accessibles en -S "P$i"
utilisant les noms donnés précédemment. L' -p 0
option est critique, sinon la commande échoue par intermittence (selon que vous vous êtes déjà connecté ou non à l'écran).
for i in `awk 'BEGIN {for (i=0;i<'${#PIDs[@]}';i++) {print i}}'`
do
screen -S "P$i" -p 0 -X stuff "set logging file debug.$i.log
"
screen -S "P$i" -p 0 -X stuff "set logging overwrite on
"
screen -S "P$i" -p 0 -X stuff "set logging on
"
screen -S "P$i" -p 0 -X stuff "source debug.init
"
done
À ce stade, vous pouvez vous attacher à n'importe quel écran en utilisant screen -rS "P$i"
et détacher en utilisant Ctrl+A+D
. Les commandes peuvent être envoyées à toutes les sessions gdb par analogie avec la section de code précédente.