¿Cómo depuro un programa MPI?


Tengo un programa MPI que compila y se ejecuta, pero me gustaría pasar a través de él para asegurarse de que nada extraño está sucediendo. Idealmente, me gustaría una forma sencilla 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 depurar MPI los programas?

 106
Author: Jay Conrod, 2008-11-30

16 answers

Como alguien dijo, TotalView es el estándar para esto. Pero te costará un brazo y una pierna.

El sitio de OpenMPI tiene una gran FAQ sobre depuración de MPI. El artículo # 6 en las preguntas frecuentes describe cómo adjuntar GDB a procesos MPI. Lea todo el asunto, hay algunos grandes consejos.

Si encuentra que tiene demasiados procesos para realizar un seguimiento, consulte Stack Trace Analysis Tool (STAT). Usamos esto en Livermore para recoger rastros de pila de potencialmente cientos de miles de procesos en ejecución y representarlos de manera inteligente a los usuarios. No es un depurador con todas las funciones (un depurador con todas las funciones nunca escalaría a núcleos de 208k), pero le dirá qué grupos de procesos están haciendo lo mismo. A continuación, puede pasar a través de un representante de cada grupo en un depurador estándar.

 52
Author: tgamblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-30 18:19:14

He encontrado gdb bastante útil. Lo uso como

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

Este es el lanzamiento de ventanas xterm en las que puedo hacer

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

Normalmente funciona bien

También puede empaquetar estos comandos juntos usando:

mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...]
 65
Author: messenjah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-18 03:24:25

Muchas de las publicaciones aquí son sobre GDB, pero no mencionas cómo adjuntar a un proceso desde el inicio. Obviamente, puede adjuntar a todos los procesos:

mpiexec -n X gdb ./a.out

Pero eso es tremendamente ineficaz ya que tendrás que rebotar para iniciar todos tus procesos. Si solo desea depurar uno (o un pequeño número de) procesos MPI, puede agregarlo como un ejecutable separado en la línea de comandos utilizando el operador ::

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

Ahora solo uno de sus procesos obtendrá GDB.

 21
Author: Wesley Bland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-03 13:42:13

Como otros han mencionado, si solo está trabajando con un puñado de procesos MPI, puede intentar usar múltiples sesiones gdb, el redoubtable valgrind o rodar su propia solución printf / logging.

Si está utilizando más procesos que eso, realmente comienza a necesitar un depurador adecuado. El OpenMPI FAQ recomienda Allinea DDTy TotalView.

Trabajo en Allinea DDT. Es un completo, gráfico depurador de código fuente así que sí, puedes:

  • Depurar o adjuntar a (más de 200k) procesos MPI
  • Paso y pausa en grupos o individualmente
  • Añadir puntos de interrupción, relojes y puntos de seguimiento
  • Captura errores de memoria y fugas

...y así sucesivamente. Si has utilizado Eclipse o Visual Studio, estarás como en casa.

Agregamos algunas características interesantes específicamente para depurar el código paralelo (ya sea MPI, multi-threaded o CUDA):

  • Las variables escalares se comparan automáticamente en todos los procesos: Sparklines mostrando valores en todos los procesos

  • También puede rastrear y filtrar los valores de variables y expresiones sobre procesos y tiempo: Valores de registro de puntos de seguimiento a lo largo del tiempo

Es ampliamente utilizado entre top500 HPC sitios, tales como ORNL, NCSA, LLNL, Jülich et. al.

La interfaz es bastante ágil; cronometramos el paso y la fusión de las pilas y variables de 220,000 procesos a 0.1 s como parte de las pruebas de aceptación en el clúster Jaguar de Oak Ridge.

@tgamblin mencionó la excelente STAT, que se integra con Allinea DDT, al igual que varios otros proyectos populares de código abierto.

 16
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-08 14:35:46
 8
Author: Chad Brewbaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-09 15:56:40

Http://github.com/jimktrains/pgdb/tree/master es una utilidad que escribí para hacer esto mismo. Hay algunos documentos y no dude en pm mí para preguntas.

Básicamente llamas 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 para que pueda acceder a él en cada host en el terminal.

 5
Author: Jim Keener,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-08 23:40:41

Usar screen junto con gdb para depurar aplicaciones MPI funciona muy bien, especialmente si xterm no está disponible o está tratando con más de unos pocos procesadores. Hubo muchas trampas en el camino con las búsquedas de stackoverflow acompañantes, así 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í por raise(SIGSTOP);, que requiere una llamada extra 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 ejecutable en segundo plano y capture el stderr. Luego 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`)

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, -S "P$RANK" le permite nombrar la pantalla para facilitar acceda más tarde, y la opción -l para bash lo 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 gdb se ha iniciado en las pantallas, puede escribir la entrada a las pantallas (para que no tenga que ingresar todas las pantallas y escribir lo mismo) utilizando el comando -X stuff de screen. Se requiere una nueva línea al final del comando. Aquí se accede a las pantallas mediante -S "P$i" utilizando los nombres previamente dados. La opción -p 0 es crítica, de lo contrario el comando falla intermitentemente (en función de si se ha conectado previamente a la pantalla o no).

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 puede adjuntar a cualquier pantalla usando screen -rS "P$i" y separar usando Ctrl+A+D. Los comandos pueden ser enviados a todas las sesiones de gdb en analogía con la sección anterior del código.

 4
Author: user3788566,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-04 16:43:06

La forma "estándar" de depurar programas MPI es usando un depurador que soporte ese modelo de ejecución.

En UNIX, TotalView se dice que tiene un buen soporte para MPI.

 3
Author: Community,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-19 16:16:17

Utilizo este pequeño método homebrewn para adjuntar depurador a procesos MPI - llama a la siguiente función, DebugWait(), justo después de MPI_Init() en tu código. Ahora, mientras los procesos esperan la entrada del teclado, tiene todo el tiempo para adjuntar el depurador a ellos y agregar puntos de interrupción. Cuando haya terminado, proporcione una entrada de un solo carácter y estará listo para comenzar.

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);
}

Por supuesto que querrías compilar esta función solo para compilaciones de depuración.

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-09 14:44:39

También está mi herramienta de código abierto, padb, que tiene como objetivo ayudar con la programación paralela. Yo lo llamo una "Herramienta de Inspección de trabajo", ya que funciona no solo como un depurador también puede funcionar, por ejemplo, como un programa paralelo superior como. Ejecutar en modo "Informe completo" le mostrará rastros de pila de cada proceso dentro de su aplicación junto con variables locales para cada función sobre cada rango (suponiendo que compiló con-g). También le mostrará las "colas de mensajes MPI" , que es la lista de sobresaliente envía y recibe por 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 qué información se muestra, consulte la página web para obtener más detalles.

Padb

 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-03 20:58:25

Si eres un usuario tmux te sentirás muy cómodo usando el script de Benedikt Morbach: tmpi

Fuente Original: https://github.com/moben/scripts/blob/master/tmpi

Tenedor: 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 enfoque xterm -e). Además puede conocer los valores de las variables en el proceso que desea simplemente haciendo un print sin tener que mover a otro panel, esto imprimirá en cada panel los valores de la variable para cada proceso.

Si no tmux usuario recomiendo encarecidamente que probarlo y ver.

 2
Author: GG1991,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-26 14:56:03
 1
Author: RSFalcon7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-01 13:11:05

El comando para adjuntar gdb a un proceso mpi está incompleto, debería ser

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

Una breve discusión de mpi y gdb se puede encontrar aquí

 1
Author: akintayo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-12 23:40:11

Hago algunas depuraciones relacionadas con MPI con trazas de registro, pero también puedes ejecutar gdb si estás 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.

 1
Author: Jim Hunziker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-23 14:13:43

Otra solución es ejecutar el código dentro de SMPI, el MPI simulado. Es un proyecto de código abierto en el que estoy involucrado. Cada rango MPI se convertirá en subprocesos del mismo proceso UNIX. A continuación, puede utilizar fácilmente gdb para escalonar los rangos de MPI.

SMPI propone otras ventajas para el estudio de las aplicaciones MPI: clairevoyance (puede observar todas las partes del sistema), reproducibilidad (varias ejecuciones conducen al mismo comportamiento exacto a menos que se especifique así), ausencia de heisenbugs (como la plataforma simulada se mantiene diferente de la host), etc.

Para más información, vea esta presentación, o esa respuesta relacionada.

 0
Author: Martin Quinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:05

Una forma bastante sencilla de depurar un programa MPI.

En la función main () añade sleep (some_seconds)

Ejecute el programa como de costumbre

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

El programa comenzará y entrará en el sueño.

Así que tendrás unos segundos para encontrar tus procesos por ps, ejecutar gdb y adjuntarlos.

Si usas algún editor como QtCreator puedes usar

Debug - > Iniciar depuración - > Adjuntar a la aplicación en ejecución

Y encontrar procesos allí.

 0
Author: stranger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-04 19:57:50