L'uso screen
insieme gdb
al debug delle applicazioni MPI funziona bene, specialmente se xterm
non è disponibile o hai a che fare con più processori. Ci sono state molte insidie lungo la strada con ricerche di stackoverflow di accompagnamento, quindi riprodurrò la mia soluzione per intero.
Innanzitutto, aggiungi il codice dopo MPI_Init per stampare il PID e fermare il programma in attesa di collegarti. La soluzione standard sembra essere un ciclo infinito; Alla fine mi sono deciso raise(SIGSTOP);
, il che richiede una chiamata extra continue
per scappare all'interno di 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);
}
Dopo la compilazione, esegui l'eseguibile in background e prendi lo stderr. È quindi possibile grep
il file stderr per alcune parole chiave (qui letterale PID) per ottenere il PID e il grado di ciascun processo.
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`)
Una sessione gdb può essere collegata a ciascun processo con gdb $MDRUN_EXE $PID
. Farlo all'interno di una sessione dello schermo consente un facile accesso a qualsiasi sessione gdb. -d -m
avvia lo schermo in modalità staccata, -S "P$RANK"
consente di denominare lo schermo per un facile accesso in un secondo momento, e l' -l
opzione per bash lo avvia in modalità interattiva e impedisce a gdb di uscire immediatamente.
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
Una volta che gdb è stato avviato nelle schermate, è possibile inserire script nelle schermate (in modo da non dover accedere a tutte le schermate e digitare la stessa cosa) usando il -X stuff
comando screen . È richiesta una nuova riga alla fine del comando. Qui è possibile accedere alle schermate -S "P$i"
utilizzando i nomi precedentemente indicati. L' -p 0
opzione è fondamentale, altrimenti il comando fallisce in modo intermittente (in base al fatto che sia stato precedentemente collegato allo schermo).
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
A questo punto puoi collegarti a qualsiasi schermo usando screen -rS "P$i"
e staccare usando Ctrl+A+D
. I comandi possono essere inviati a tutte le sessioni gdb in analogia con la precedente sezione di codice.