Comment puis-je déboguer un programme MPI?

j'ai un programme MPI qui compile et exécute, mais je voudrais le PARCOURIR pour m'assurer que rien de bizarre ne se passe. Idéalement, je voudrais un moyen simple d'attacher GDB à n'importe quel processus particulier, mais je ne suis pas vraiment sûr si c'est possible ou comment le faire. Une alternative serait que chaque processus écrive la sortie de débogage dans un fichier log séparé, mais cela ne donne pas vraiment la même liberté qu'un débogueur.

y a-t-il de meilleures approches? Comment faites-vous déboguer les programmes MPI?

106
demandé sur Jay Conrod 2008-11-30 23:02:21

16 réponses

comme quelqu'un d'autre a dit, TotalView est la norme pour cela. Mais il va vous coûter un bras et une jambe.

le site OpenMPI a une grande FAQ sur le débogage MPI . Le point n ° 6 de la FAQ décrit comment attacher GDB aux processus MPI. Lire l'intégralité de chose, il ya quelques conseils.

si vous trouvez que vous avez beaucoup trop de processus pour garder une trace de, cependant, Vérifiez Stack Trace Outil d'analyse (STAT) . Nous l'utilisons à Livermore pour collecter des traces de pile de centaines de milliers de processus en cours d'exécution et pour les représenter intelligemment aux utilisateurs. Il ne s'agit pas d'un débogueur complet (un débogueur complet n'évoluerait jamais vers des noyaux de 208 K), mais il vous indiquera quels groupes de processus font la même chose. Vous pouvez alors passer par un représentant de chaque groupe dans un débogueur standard.

52
répondu tgamblin 2013-06-30 18:19:14

j'ai trouvé gdb très utile. Je l'utilise comme

mpirun -np <NP> xterm -e gdb ./program 

ceci lance les fenêtres xterm dans lesquelles je peux faire

run <arg1> <arg2> ... <argN>

fonctionne généralement bien

vous pouvez aussi empaqueter ces commandes ensemble en utilisant:

mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...]
65
répondu messenjah 2015-09-18 03:24:25

beaucoup de ces messages sont sur GDB, mais ne mentionnent pas comment s'attacher à un processus à partir du démarrage. Évidemment, vous pouvez attacher à tous les processus:

mpiexec -n X gdb ./a.out

mais c'est extrêmement inefficace car vous devrez rebondir pour démarrer tous vos processus. Si vous voulez juste déboguer un (ou un petit nombre) processus MPI, vous pouvez ajouter cela comme un exécutable séparé sur la ligne de commande en utilisant l'opérateur : :

mpiexec -n 1 gdb ./a.out : -n X-1 ./a.out

maintenant, un seul de vos processus va recevoir GDB.

21
répondu Wesley Bland 2013-09-03 13:42:13

comme d'autres l'ont mentionné, si vous travaillez seulement avec une poignée de processus MPI , vous pouvez essayer d'utiliser plusieurs sessions gdb , le redoutable valgrind ou lancer votre propre solution printf / logging.

si vous utilisez plus de processus que cela, vous commencez vraiment à avoir besoin d'un bon débogueur. Le OpenMPI FAQ recommande à la fois Allinea DDT et TotalView .

je travaille sur Allinea DDT . C'est un débogueur de code source graphique complet, donc oui, vous pouvez:

  • Debug ou attacher (plus de 200k) processus MPI
  • étape et les mettre en pause en groupes ou individuellement
  • Ajouter des points d'arrêt, les montres et les points de trace ne
  • erreurs de mémorisation et fuites

...et ainsi de suite. Si vous avez utilisé Eclipse ou Visual Studio, vous serez chez vous.

nous avons ajouté quelques caractéristiques intéressantes spécifiquement pour le débogage code parallèle (que ce soit MPI, multi-threaded ou CUDA):

  • les variables scalaires sont automatiquement comparées dans tous les processus: Sparklines showing values across processes

  • vous pouvez aussi tracer et filtrer les valeurs des variables et des expressions au cours des processus et du temps: Tracepoints log values over time

Il est largement utilisé parmi les top500 HPC sites, tels que ORNL , NCSA , LLNL , Jülich et. Al.

l'interface est assez snappy; nous avons chronométré pas à pas et la fusion des piles et des variables de 220 000 processus à 0,1 s dans le cadre des essais d'acceptation du cluster Jaguar D'Oak Ridge.

@tgamblin a mentionné l'excellent STAT , qui s'intègre avec Allinea DDT , comme le font plusieurs autres projets populaires open source.

16
répondu Mark 2017-02-08 14:35:46
8
répondu Chad Brewbaker 2010-03-09 15:56:40

http://github.com/jimktrains/pgdb/tree/master est un utilitaire que j'ai écrit pour faire cette chose. Il y a des docteurs et n'hésitez pas à me poser des questions.

vous appelez fondamentalement un programme perl qui enveloppe GDB et funnels il est IO à un serveur central. Cela permet à GDB de fonctionner sur chaque hôte et vous permet d'y accéder sur chaque hôte du terminal.

5
répondu Jim Keener 2009-04-08 23:40:41

en utilisant screen avec gdb pour déboguer les applications MPI fonctionne bien, surtout si xterm n'est pas disponible ou si vous avez affaire à plus de quelques processeurs. Il y a eu de nombreux écueils en cours de route avec les recherches stackoverflow, donc je vais reproduire ma solution dans son intégralité.

d'abord, ajoutez le code après MPI_Init pour imprimer le PID et arrêtez le programme pour attendre que vous attachiez. La solution standard semble être une boucle infinie; J'ai finalement choisi raise(SIGSTOP); , ce qui nécessite un appel supplémentaire de continue pour m'échapper à l'intérieur de 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 compilation, Lancez l'exécutable en arrière-plan et attrapez le stderr. Vous pouvez ensuite grep le fichier stderr pour un mot-clé (ici littéralement PID) 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 }' $PIDFILE`)
RANKs=(`awk '{print }' $PIDFILE`)

une session gdb peut être attachée à chaque processus avec gdb $MDRUN_EXE $PID . Le faire dans le cadre d'une session écran permet 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 le -l option pour bash démarre en mode interactif et garde 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 commencé dans les écrans, vous pouvez script entrée dans les écrans (afin que vous n'ayez pas à entrer chaque écran et taper la même chose) en utilisant la commande -X stuff de l'écran. Un retour à la ligne est à la fin de la commande. Ici, les écrans sont accessibles par -S "P$i" en utilisant les noms donnés précédemment. L'option -p 0 est critique, sinon la commande échoue de façon intermittente (selon que vous vous êtes ou non précédemment attaché à 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 point, vous pouvez joindre à n'importe quel écran en utilisant screen -rS "P$i" et détacher en utilisant Ctrl+A+D . Des commandes peuvent être envoyées à toutes les sessions gdb en analogie avec la section précédente du code.

4
répondu user3788566 2014-07-04 16:43:06

la façon "standard" de déboguer les programmes MPI est d'utiliser un débogueur qui supporte ce modèle d'exécution.

Sur UNIX, TotalView a de bonnes suppoort de MPI.

3
répondu Community 2013-07-19 16:16:17

j'utilise cette petite méthode maison pour attacher le débogueur aux processus MPI - appelez la fonction suivante, DebugWait(), juste après MPI_Init() dans votre code. Maintenant, pendant que les processus attendent les entrées au clavier, vous avez tout le temps d'attacher le débogueur à eux et d'ajouter des points de rupture. Lorsque vous avez terminé, fournir un caractère unique d'entrée et vous êtes prêt à aller.

static void DebugWait(int rank) {
    char    a;

    if(rank == 0) {
        scanf("%c", &a);
        printf("%d: Starting now\n", rank);
    } 

    MPI_Bcast(&a, 1, MPI_BYTE, 0, MPI_COMM_WORLD);
    printf("%d: Starting now\n", rank);
}

bien sûr, vous voudriez compiler cette fonction pour les constructions de débogage seulement.

2
répondu 2009-05-09 14:44:39

Il ya aussi mon outil open-source, padb, qui vise à aider à la programmation parallèle. Je l'appelle un" outil D'Inspection du travail " car il ne fonctionne pas seulement comme un débogueur peut également fonctionner par exemple comme un programme parallèle. Exécutez en mode "rapport complet" il vous montrera les traces de chaque processus dans votre application avec des variables locales pour chaque fonction sur chaque rang (en supposant que vous compilé avec-g). Il vous montrera aussi les "files D'attente de messages MPI", c'est-à-dire la liste des envoie et reçoit pour chaque grade dans le travail.

en plus de montrer le rapport complet, il est également possible de dire à padb de zoomer sur des bits individuels d'information dans le travail, il y a une myriade d'options et d'éléments de configuration pour contrôler ce que l'information est montrée, voir la page web pour plus de détails.

Padb

2
répondu 2009-12-03 20:58:25

si vous êtes un utilisateur tmux vous vous sentirez très à l'aise en utilisant le script de Benedikt Morbach : tmpi

source originale: https://github.com/moben/scripts/blob/master/tmpi

fourche: https://github.com/Azrael3000/tmpi

avec lui vous avez plusieurs panneaux (nombre de processus) tous synchronisé (chaque commande est copiée sur tous les panneaux ou processus en même temps donc vous économisez beaucoup de temps en comparant avec l'approche xterm -e ). En outre, vous pouvez connaître les valeurs des variables dans le processus que vous voulez juste faire un print sans avoir à passer à un autre panneau, cela affichera sur chaque panneau les valeurs de la variable pour chaque processus.

si vous n'êtes pas un utilisateur tmux je recommande fortement de l'essayer et de voir.

2
répondu GG1991 2018-04-26 14:56:03

la commande pour attacher gdb à un processus mpi est incomplète, elle devrait être

mpirun -np <NP> xterm -e gdb ./program 

une brève discussion de mpi et gdb peut être trouvé ici

1
répondu akintayo 2015-07-12 23:40:11

je fais du débogage lié au MPI avec des traces de journalisation, mais vous pouvez également exécuter gdb si vous utilisez mpich2: MPICH2 et gdb . Cette technique est une bonne pratique en général lorsqu'il s'agit d'un processus délicat à lancer à partir d'un débogueur.

1
répondu Jim Hunziker 2015-11-23 14:13:43

une autre solution est d'exécuter votre code dans SMPI, le MPI simulé. C'est un projet open source dans lequel je suis impliqué. Chaque rang MPI sera converti en threads du même processus UNIX. Vous pouvez alors facilement utiliser gdb pour faire un pas dans les rangs MPI.

SMPI propose d'autres avantages à l'étude des applications MPI: clairevoyance (vous pouvez observer toutes les parties du système), reproductibilité (plusieurs passages conduisent au même comportement exact sauf si vous le spécifiez ainsi), absence de heisenbugs (la plate-forme simulée étant maintenue différente de la plate-forme hôte), etc.

pour plus de renseignements, voir cette présentation , ou réponse connexe .

0
répondu Martin Quinson 2017-05-23 12:18:05

une façon assez simple de déboguer un programme MPI.

Dans la fonction main () ajouter le sommeil (some_seconds)

Exécuter le programme comme d'habitude

$ mpirun -np <num_of_proc> <prog> <prog_args>

programme va commencer et entrer dans le sommeil.

ainsi vous aurez quelques secondes pour trouver vos processus par ps, exécuter gdb et les attacher.

si vous utilisez un éditeur comme QtCreator vous pouvez utiliser""

Debug->Démarrer le débogage->Joindre à l'exécution de l'application

et vous y trouver des processus.

0
répondu stranger 2018-09-04 19:57:50