mpiEmpezando con mpi


Observaciones

MPI es un estándar para la comunicación entre un grupo de procesos distribuidos (o locales). Incluye rutinas para enviar y recibir datos, comunicarse colectivamente y otras tareas más complejas.

El estándar proporciona una API para C y Fortran, pero también existen enlaces a otros lenguajes.

Versiones

Versión Estándar Fecha de lanzamiento
1 mpi-report-1.3-2008-05-30.pdf 1994-05-05
2.0 mpi2-report.pdf 2003-09-15
2.2 mpi22-report.pdf 2009-09-04
3.0 mpi30-report.pdf 2012-09-21
3.1 mpi31-report.pdf 2015-06-04

Hola Mundo!

Tres cosas son generalmente importantes cuando se comienza a aprender a usar MPI. Primero, debe inicializar la biblioteca cuando esté listo para usarla (también debe finalizarla cuando haya terminado). Segundo, querrá saber el tamaño de su comunicador (lo que usa para enviar mensajes a otros procesos). Tercero, querrá saber su rango dentro de ese comunicador (en qué número de proceso está usted dentro de ese comunicador).

#include <mpi.h>
#include <stdio.h>

int main(int argc, char **argv) {
    int size, rank;
    int res;

    res = MPI_Init(&argc, &argv);
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Init failed\n");
        exit (0);
    }

    res = MPI_Comm_size(MPI_COMM_WORLD, &size);
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Comm_size failed\n");
        exit (0);
    }
    res = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Comm_rank failed\n");
        exit (0);
    }

    fprintf(stdout, "Hello World from rank %d of %d~\n", rank, size);

    res = MPI_Finalize();
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Finalize failed\n");
        exit (0);
    }
}
 

Si ejecuta este programa de esta manera:

mpiexec -n 2 ./hello
 

Usted esperaría obtener una salida como esta:

Hello World from rank 0 of 2!
Hello World from rank 1 of 2!
 

También puede obtener esa salida hacia atrás (consulte http://stackoverflow.com/a/17571699/491687 ) para obtener más información sobre esto:

Hello World from rank 1 of 2!
Hello World from rank 0 of 2!
 

Iniciar / Finalizar

Antes de ejecutar cualquier comando MPI, el entorno debe inicializarse y finalizarse al final:

int main(int argc, char** argv)
{
    int res;
    res = MPI_Init(&argc,&argv);
    if (res != MPI_SUCCESS)
    {
      fprintf (stderr, "MPI_Init failed\n");
      exit (0);
    }
    ...
    res = MPI_Finalize();
    if (res != MPI_SUCCESS)
    {
      fprintf (stderr, "MPI_Finalize failed\n");
      exit (0);
    }
}
 

Rango y tamaño

Para obtener el tamaño de un comunicador (por ejemplo, MPI_COMM_WORLD ) y el rango del proceso local dentro de él:

int rank, size;
int res;
MPI_Comm communicator = MPI_COMM_WORLD;

res = MPI_Comm_rank (communicator, &rank);
if (res != MPI_SUCCESS)
{
  fprintf (stderr, "MPI_Comm_rank failed\n");
  exit (0);
}
res = MPI_Comm_size (communicator, &size);
if (res != MPI_SUCCESS)
{
  fprintf (stderr, "MPI_Comm_size failed\n");
  exit (0);
}
 

Valores de retorno de llamadas MPI

Casi cualquier llamada MPI devuelve un código de error entero, lo que significa el éxito de la operación. Si no se produce ningún error, el código de retorno es MPI_SUCCESS :

if (MPI_Some_op(...) != MPI_SUCCESS)
{
   // Process error
}
 

Si se produce un error, MPI llama a un controlador de errores asociado con el comunicador, la ventana o el objeto de archivo antes de regresar al código de usuario. Hay dos manejadores de errores predefinidos (el usuario puede definir manejadores de errores adicionales):

  • MPI_ERRORS_ARE_FATAL : los errores resultan en la terminación del programa MPI
  • MPI_ERRORS_RETURN : los errores provocan que el código de error se devuelva al usuario

El controlador de errores predeterminado para comunicadores y ventanas es MPI_ERRORS_ARE_FATAL ; para los objetos de archivo es MPI_ERRORS_RETURN . El controlador de errores para MPI_COMM_WORLD también se aplica a todas las operaciones que no están específicamente relacionadas con un objeto (por ejemplo, MPI_Get_count ). Por lo tanto, verificar el valor de retorno de las operaciones sin E / S sin configurar el controlador de errores en MPI_ERRORS_RETURN es redundante ya que las llamadas MPI erróneas no se devolverán.

// The execution will not reach past the following line in case of error
int res = MPI_Comm_size(MPI_COMM_WORLD, &size);
if (res != MPI_SUCCESS)
{
    // The following code will never get executed
    fprintf(stderr, "MPI_Comm_size failed: %d\n", res);
    exit(EXIT_FAILURE);
}
 

Para habilitar el procesamiento de errores del usuario, primero se debe cambiar el controlador de errores de MPI_COMM_WORLD :

MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);

int res = MPI_Comm_size(MPI_COMM_WORLD, &size);
if (res != MPI_SUCCESS)
{
    fprintf(stderr, "MPI_Comm_size failed: %d\n", res);
    exit(EXIT_FAILURE);
}
 

El estándar MPI no requiere que las implementaciones de MPI puedan recuperarse de los errores y continuar la ejecución del programa.