Tengo un programa MPI que compila y ejecuta, pero me gustaría revisarlo para asegurarme de que no ocurra nada extraño. Idealmente, me gustaría una forma simple de adjuntar GDB a cualquier proceso en particular, pero no estoy realmente seguro de si eso es posible o cómo hacerlo. Una alternativa sería hacer que cada proceso escriba la salida de depuración en un archivo de registro separado, pero esto realmente no da la misma libertad que un depurador.
¿Hay mejores enfoques? ¿Cómo se depuran los programas MPI?
He encontrado gdb bastante útil. Lo uso como
Esto lanza las ventanas xterm en las que puedo hacer
por lo general funciona bien
También puede empaquetar estos comandos juntos usando:
fuente
<file>
y pasando-x <file>
a gdb.Muchas de las publicaciones aquí son sobre GDB, pero no mencionan cómo adjuntar a un proceso desde el inicio. Obviamente, puede adjuntar a todos los procesos:
Pero eso es tremendamente ineficaz, ya que tendrá que rebotar para iniciar todos sus procesos. Si solo desea depurar un (o un pequeño número de) procesos MPI, puede agregarlo como un ejecutable separado en la línea de comando utilizando el
:
operador:Ahora solo uno de sus procesos obtendrá GDB.
fuente
Como otros han mencionado, si solo está trabajando con un puñado de procesos MPI, puede intentar usar múltiples sesiones de gdb , el valgrind reducible o rodar su propia solución printf / logging.
Si está utilizando más procesos que eso, realmente comienza a necesitar un depurador adecuado. Las preguntas frecuentes de OpenMPI recomiendan Allinea DDT y TotalView .
Yo trabajo en Allinea DDT . Es un depurador de código fuente gráfico con todas las funciones, así que sí, puede:
...y así. Si ha usado Eclipse o Visual Studio, estará en casa.
Agregamos algunas características interesantes específicamente para depurar código paralelo (ya sea MPI, multiproceso o CUDA):
Las variables escalares se comparan automáticamente en todos los procesos: (fuente: allinea.com )
También puede rastrear y filtrar los valores de variables y expresiones sobre procesos y tiempo:
Es ampliamente utilizado entre los 500 principales sitios de HPC, como ORNL , NCSA , LLNL , Jülich et. Alabama.
La interfaz es bastante ágil; cronometramos el paso y la fusión de las pilas y variables de 220,000 procesos a 0.1s como parte de las pruebas de aceptación en el clúster Jaguar de Oak Ridge.
@tgamblin mencionó el excelente STAT , que se integra con Allinea DDT , al igual que otros proyectos populares de código abierto.
fuente
http://valgrind.org/ nuf dijo
Enlace más específico: Depuración de programas paralelos MPI con Valgrind
fuente
Si eres
tmux
usuario, te sentirás muy cómodo usando el script de Benedikt Morbach :tmpi
Fuente original:
https://github.com/moben/scripts/blob/master/tmpiFork: https://github.com/Azrael3000/tmpi
Con él, tiene varios paneles (número de procesos) todos sincronizados (cada comando se copia en todos los paneles o procesos al mismo tiempo, por lo que ahorra mucho tiempo en comparación con el
xterm -e
enfoque). Además, puede conocer los valores de las variables en el proceso que desea hacerprint
sin tener que pasar a otro panel, esto imprimirá en cada panel los valores de la variable para cada proceso.Si no eres
tmux
usuario, te recomiendo que lo pruebes y lo veas.fuente
http://github.com/jimktrains/pgdb/tree/master es una utilidad que escribí para hacer esto mismo. Hay algunos documentos y no dude en enviarme preguntas.
Básicamente llama a un programa perl que envuelve GDB y canaliza su IO a un servidor central. Esto permite que GDB se ejecute en cada host y que pueda acceder a él en cada host en la terminal.
fuente
El uso
screen
junto con lagdb
depuración de aplicaciones MPI funciona bien, especialmente sixterm
no está disponible o si se trata de más de unos pocos procesadores. Hubo muchos escollos en el camino con las búsquedas de stackoverflow que lo acompañan, por lo que reproduciré mi solución en su totalidad.Primero, agregue código después de MPI_Init para imprimir el PID y detenga el programa para esperar a que lo adjunte. La solución estándar parece ser un bucle infinito; Finalmente me decidí
raise(SIGSTOP);
, lo que requiere una llamada adicionalcontinue
para escapar dentro de gdb.Después de compilar, ejecute el ejecutable en segundo plano y capture el stderr. Luego puede
grep
usar el archivo stderr para alguna palabra clave (aquí PID literal) para obtener el PID y el rango de cada proceso.Se puede adjuntar una sesión gdb 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, le-S "P$RANK"
permite asignarle un nombre a la pantalla para acceder fácilmente más tarde, y la-l
opción de bash la inicia en modo interactivo y evita que gdb salga de inmediato.Una vez que gdb ha comenzado en las pantallas, puede ingresar la secuencia de comandos en las pantallas (para que no tenga que ingresar a todas las pantallas y escribir lo mismo) usando el
-X stuff
comando de pantalla . Se requiere una nueva línea al final del comando. Aquí se accede a las pantallas-S "P$i"
utilizando los nombres dados previamente. La-p 0
opción es crítica, de lo contrario, el comando falla intermitentemente (en función de si se ha conectado o no previamente a la pantalla).En este punto, puede adjuntarlo a cualquier pantalla usando
screen -rS "P$i"
y desconectar usandoCtrl+A+D
. Se pueden enviar comandos a todas las sesiones de gdb en analogía con la sección de código anterior.fuente
También está mi herramienta de código abierto, padb, que tiene como objetivo ayudar con la programación paralela. Lo llamo una "Herramienta de inspección de trabajos", ya que funciona no solo como un depurador, sino que también puede funcionar, por ejemplo, como un programa paralelo superior. Ejecutar en modo "Informe completo" le mostrará los rastros de la pila de cada proceso dentro de su aplicación junto con variables locales para cada función en cada rango (suponiendo que compiló con -g). También le mostrará las "colas de mensajes MPI", que es la lista de envíos y recibos pendientes para cada rango dentro del trabajo.
Además de mostrar el informe completo, también es posible decirle a Padb que amplíe los bits individuales de información dentro del trabajo, hay una gran cantidad de opciones y elementos de configuración para controlar la información que se muestra, consulte la página web para obtener más detalles.
Padb
fuente
La forma "estándar" de depurar programas MPI es mediante el uso de un depurador que admita ese modelo de ejecución.
En UNIX, se dice que TotalView tiene un buen soporte para MPI.
fuente
Utilizo este pequeño método casero para adjuntar el depurador a los procesos MPI: llame a la siguiente función, DebugWait (), justo después de MPI_Init () en su código. Ahora, mientras los procesos esperan la entrada del teclado, tiene todo el tiempo para adjuntarles el depurador y agregar puntos de interrupción. Cuando haya terminado, proporcione una entrada de un solo carácter y estará listo para comenzar.
Por supuesto, desearía compilar esta función solo para compilaciones de depuración.
fuente
gethostname(hostname, sizeof(hostname)); printf("PID %d on host %s ready for attach\n", getpid(), hostname);
. Luego, se adjunta al proceso escribiendorsh <hostname_from_print_statement>
y finalmentegdb --pid=<PID_from_print_statement>
.El comando para adjuntar gdb a un proceso mpi está incompleto, debería ser
Una breve discusión de mpi y gdb se puede encontrar aquí
fuente
Una manera bastante simple de depurar un programa MPI.
En la función main () agregue sleep (some_seconds)
Ejecute el programa como siempre
El programa comenzará y se dormirá.
Entonces tendrá unos segundos para encontrar sus procesos por ps, ejecute gdb y adjúntelos.
Si usa algún editor como QtCreator, puede usar
Depuración-> Iniciar depuración-> Adjuntar a la aplicación en ejecución
y encontrar sus procesos allí.
fuente
Realizo algunas depuraciones relacionadas con MPI con trazas de registro, pero también puede ejecutar gdb si está usando mpich2: MPICH2 y gdb . Esta técnica es una buena práctica en general cuando se trata de un proceso que es difícil de iniciar desde un depurador.
fuente
mpirun -gdb
Gracias a http://www.ncsa.illinois.edu/UserInfo/Resources/Hardware/CommonDoc/mpich2_gdb.html ( enlace a archivo )
fuente
Otra solución es ejecutar su código dentro de SMPI, el MPI simulado. Ese es un proyecto de código abierto en el que estoy involucrado. Cada rango MPI se convertirá en hilos del mismo proceso UNIX. Luego puede usar fácilmente gdb para subir los rangos de MPI.
SMPI propone otras ventajas para el estudio de aplicaciones MPI: clarividencia (puede observar todas las partes del sistema), reproducibilidad (varias ejecuciones conducen al mismo comportamiento exacto a menos que lo especifique), ausencia de errores detectados (ya que la plataforma simulada se mantiene diferente del anfitrión), etc.
Para obtener más información, consulte esta presentación o la respuesta relacionada .
fuente