Computación Matricial y Paralela
Programación con Paso de Mensajes.
MPI
Javier Cuenca
Domingo Giménez
Dpto. de Ingeniería y Tecnología de Computadores
Dpto. de Informática y Sistemas
Universidad de Murcia
http://dis.um.es/~domingo
1
2
Contenido
Introducción
Ejemplo: hello.c
Ejemplo de uso
Tipos de comunicación
Comunicación asíncrona
Comunicaciones colectivas
Agrupamiento de datos
Comunicadores
Introducción
3
ScaLAPACK
Paso de mensajes
Direccionamiento
global
PBLAS
LAPACK
BLACS
Dependiente de la
plataforma
BLAS
Comunicaciones: PVM, MPI
Direccionamiento
local
Independiente de la
plataforma
Secuencial
4
Introducción
Previamente PVM: Parallel Virtual Machine
MPI: Message Passing Interface
Una especificación para paso de mensajes
La primera librería de paso de mensajes estándar y portable
Por consenso MPI Forum. Participantes de unas 40 organizaciones
Acabado y publicado en mayo 1994. Actualizado en junio 1995
MPI2, HMPI
Introducción.
¿Qué ofrece?
Estandarización
5
Portabilidad:
heterogéneos, ...
multiprocesadores,
multicomputadores,
redes,
Buenas prestaciones, ..., si están disponibles para el sistema
Amplia funcionalidad
Implementaciones libres (mpich, lam, ...)
6
Introducción.
Procesos
Programa MPI: conjunto de procesos autonomos
Cada proceso puede ejecutar codigo diferente
Procesos comunican via primitivas MPI
Proceso: secuencial o multhreads
MPI no proveé mecanismos para situar procesos en procesadores. Eso
es misión de cada implementación en cada plataforma
MPI 2.0:
Es posible la creación/borrado de procesos dinámicamente durante
ejecución
Es posible la ejecución remota de procesos
7
Ejemplo: hello.c
#include <stdio.h>
#include <string.h>
#include "mpi.h"
main(int argc, char*argv[]) {
int name, p, source, dest, tag = 0;
char message[100];
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&name);
MPI_Comm_size(MPI_COMM_WORLD,&p);
Ejemplo: hello.c
8
int name, p, source, dest, tag = 0;
char message[100];
MPI_Status status;
#include <stdio.h>
#include <string.h>
if (name != 0)
#include "mpi.h"
{
main(int argc, char*argv[]) {
printf("Processor %d of %d\n",name, p);
sprintf(message,"greetings from process %d!", name);
dest = 0;
MPI_Send(message, strlen(message)+1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
}
else
{
printf("processor 0, p = %d \n",p);
for(source=1; source < p; source++)
{
MPI_Recv(message,100, MPI_CHAR, source, tag, MPI_COMM_WORLD, &status);
printf("%s\n",message);
}
}
MPI_Finalize();
}
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&name);
MPI_Comm_size(MPI_COMM_WORLD,&p);
Ejemplo: hello.c
9
int name, p, source, dest, tag = 0;
char message[100];
MPI_Status status;
#include <stdio.h>
#include <string.h>
if (name != 0)
#include "mpi.h"
{
main(int argc, char*argv[]) {
printf("Processor %d of %d\n",name, p);
sprintf(message,"greetings from process %d!", name);
dest = 0;
$ make hello
MPI_Send(message, strlen(message)+1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
}
cc migrate fast hello.c o hello lmpi lrt pthread
else
MPI_Init(&argc,&argv);
{
$ dmpirun np 4 hello
MPI_Comm_rank(MPI_COMM_WORLD,&name);
printf("processor 0, p = %d \n",p);
Processor 1 of 4
MPI_Comm_size(MPI_COMM_WORLD,&p);
for(source=1; source < p; source++)
Processor 2 of 4
{
Processor 3 of 4
MPI_Recv(message,100, MPI_CHAR, source, tag, MPI_COMM_WORLD, &status);
processor 0, p = 4
printf("%s\n",message);
}
}
greetings from process 1!
MPI_Finalize();
greetings from process 2!
}
greetings from process 3!
$
Ejemplo de uso
10
Compilación:
Prometeo (Compaq HPC160 UNIX con MPI específico):
make programa
cc -migrate -fast programa.c -o programa -lmpi -lrt -pthread
PC con linux mpich:
mpicc programa.c -lmpi
Ejecución:
Prometeo:
dmpirun – np numero_procesos programa
PC linux:
mpirun – np numero_procesos -machinefile fichmaq programa
11
Ejemplo de uso
Fichero cabecera:
#include <mpi.h>
Formato de las funciones:
error=MPI_nombre(parámetros ...)
Inicialización:
int MPI_Init ( int *argc , char ***argv )
Comunicador: Conjunto de procesos en que se hacen comunicaciones
MPI_COMM_WORD , el mundo de los procesos MPI
12
Ejemplo de uso
Identificación de procesos:
MPI_Comm_rank ( MPI_Comm comm , int *rank)
Procesos en el comunicador:
MPI_Comm_size ( MPI_Comm comm , int *size)
Finalización:
int MPI_Finalize ( )
Ejemplo de uso
MENSAJE: Formado por un cierto número de elementos de un tipo MPI
Tipos MPI Básicos:
13
MPI_CHAR
MPI_SHORT
MPI_INT
MPI_LONG
MPI_UNSIGNED_CHAR
MPI_UNSIGNED_SHOT
MPI_UNSIGNED
MPI_UNSIGNED_LONG
MPI_FLOAT
MPI_DOUBLE
MPI_LONG_DOUBLE
MPI_BYTE
MPI_PACKED
signed char
signed short int
signed int
signed long int
unsigned
unsigned
unsigned int
unsigned
float
double
long double
char
short int
long int
Tipos MPI Derivados: los construye el programador
14
Ejemplo de uso
Envío:
int MPI_Send ( void *buffer , int contador , MPI_Datatype
tipo , int destino , int tag , MPI_Comm comunicador )
Recepción:
int MPI_Recv ( void *buffer , int contador , MPI_Datatype
tipo , int origen , int tag , MPI_Comm comunicador ,
MPI_Status *estado)
MPI_ANY_TAG
MPI_ANY_SOURCE
Tipos de Comunicación
15
Envío:
Envío síncrono: MPI_Ssend
Acaba cuando la recepción empieza
Envío con buffer: MPI_Bsend
Acaba siempre, independiente del receptor
Envío estándar: MPI_Send
Síncrono o con buffer
Envío “ ready” : MPI_Rsend
Acaba independiente de que acabe la recepción
Recepción: MPI_Recv
Acaba cuando se ha recibido un mensaje.
Comunicación Asíncrona
(nonblocking)
16
MPI_Isend(buf, count, datatype, dest, tag, comm,
request)
MPI_Irecv(buf, count, datatype, source, tag, comm,
request)
Parámetro request para saber si la operación ha acabado
MPI_Wait( )
vuelve si la operación se ha completado. Espera hasta que se completa
MPI_Test( )
devuelve un flag diciendo si la operación se ha completado
Comunicación Asíncrona
(nonblocking)
17
Ejemplos:
hello_nonblocking.c
nblock.c
Comunicación Asíncrona
(nonblocking)
18
Ejemplo: hello_nonblocking.c (1/2)
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&name);
MPI_Comm_size(MPI_COMM_WORLD,&p);
p_requests = (MPI_Request *) malloc ( (p+1) * sizeof(MPI_Request) );
if (name != 0)
{
printf(message,"greetings from process %d!",name);
dest = 0;
MPI_Isend(message, strlen(message)+1, MPI_CHAR, dest, tag, MPI_COMM_WORLD,
&request);
printf("Procesador %d ya ha hecho el ISEND al procesador 0\n",name);
MPI_Wait(&request,&status);
printf("Procesador %d ya ha pasado el WAIT tras envio\n",name);
}
Comunicación Asíncrona
(nonblocking)
19
Ejemplo: hello_nonblocking.c (2/2)
else
{
for(source=1; source < p; source++)
{
MPI_Irecv(messages[source],100, MPI_CHAR, MPI_ANY_SOURCE, tag,
MPI_COMM_WORLD, &p_requests[source]);
printf("Proc. 0 ya ha hecho IRECV para recibir de source=%d\n\n",source);
}
for(source=1; source < p; source++)
{
MPI_Wait(&p_requests[source],&status);
printf("Tras el Wait del Receive: %s\n",messages[source]);
}
}
free(p_requests);
Comunicación Asíncrona
(nonblocking)
20
Ejemplo: hello_nonblocking.c (2/2)
else
{
for(source=1; source < p; source++)
{
MPI_Irecv(messages[source],100, MPI_CHAR, source, tag, MPI_COMM_WORLD,
Proc. 0 ya ha hecho el IRECV para recibir de source=1
Proc. 0 ya ha hecho el IRECV para recibir de source=2
Proc. 0 ya ha hecho el IRECV para recibir de source=3
Tras el Wait del Receive: greetings from process 2!
Tras el Wait del Receive: greetings from process 3!
Tras el Wait del Receive: greetings from process 1!
printf("Proc. 0 ya ha hecho IRECV para recibir de source=%d\n\n",source);
}
&p_requests[source]);
Procesador 2 ya ha hecho el ISEND al procesador 0
Procesador 2 ya ha pasado el WAIT tras envio
for(source=1; source < p; source++)
{
MPI_Wait(&p_requests[source],&status);
printf("Tras el Wait del Receive: %s\n",messages[source]);
Procesa
Comentarios de: Programación con paso de mensajes. MPI - Computación Matricial y Paralela (0)
No hay comentarios