Usando screen
junto con gdb
para depurar aplicaciones MPI funciona muy bien, sobre todo si xterm
no está disponible o que está tratando con más de un par de procesadores. Hubo muchas trampas en el camino con las búsquedas simultáneas de stackoverflow, así que reproduciré mi solución por completo.
Primero, agregue el código después de MPI_Init para imprimir el PID y detenga el programa para esperar que lo adjunte. La solución estándar parece ser un ciclo infinito; Finalmente me decidí por raise(SIGSTOP);
, que requiere una llamada adicional de continue
para escapar dentro 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);
}
Después de compilar, ejecute el archivo ejecutable en segundo plano y capture el stderr. A continuación, puede grep
el archivo stderr para alguna palabra clave (aquí PID literal) para obtener el PID y el rango de cada proceso.
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 sesión de GDB se puede unir a cada proceso con gdb $MDRUN_EXE $PID
. Hacerlo dentro de una sesión de pantalla permite un fácil acceso a cualquier sesión de gdb.-d -m
inicia la pantalla en modo separado, -S "P$RANK"
le permite poner nombre a la pantalla para acceder fácilmente más tarde, y la opción -l
de bash la inicia en modo interactivo y evita que gdb salga inmediatamente.
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 vez que el BGF ha comenzado en las pantallas, se puede introducir secuencia de comandos para las pantallas (de modo que usted no tiene que entrar en cada pantalla y escriba la misma cosa) con el comando de pantalla -X stuff
. Se requiere una nueva línea al final del comando. Aquí se accede a las pantallas por -S "P$i"
usando los nombres dados previamente. La opción -p 0
es crítica; de lo contrario, el comando falla de forma intermitente (en función de si previamente se ha adjuntado o no a la pantalla).
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
En este punto se puede conectar a cualquier pantalla utilizando screen -rS "P$i"
y separar usando Ctrl+A+D
. Los comandos se pueden enviar a todas las sesiones de gdb en analogía con la sección de código anterior.
A partir de 2010 [Allinea DDT] (http://www.olcf.ornl.gov/2010/07/12/upgrade-adds-muscle-to-debugger/) es un depurador con todas las funciones que escala a más de 208k núcleos – Mark
Así que continuaré y votaré la respuesta de @ Mark aquí. DDT es bueno. Pruébalo también. TotalView también se integra con STAT ahora, por lo que si su sitio tiene una instalación de TotalView, puede probarlo también. LLNL mantiene TotalView y DDT, y es agradable que TotalView finalmente tenga una dura competencia. – tgamblin
Me gustaría secundar el enlace a las preguntas frecuentes sobre la depuración de MPI (http://www.open-mpi.org/faq/?category=debugging#serial-debuggers). Específicamente, la viñeta 6 es una buena, rápida y fácil (¡incluso para mí!) Para comprender la forma de, al menos, depurar un proceso individual. – Jeff