0% encontró este documento útil (0 votos)
28 vistas39 páginas

Ttrasp 3.3

El documento aborda el uso de operaciones colectivas en MPI con un enfoque en las versiones que permiten un número variable de elementos por proceso. Se discuten diferentes modos de comunicación, incluyendo el envío y recepción de datos, así como las ventajas y desventajas del uso de buffering. También se tratan las comunicaciones no bloqueantes y cómo estas pueden ayudar a evitar deadlocks en la programación paralela.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
28 vistas39 páginas

Ttrasp 3.3

El documento aborda el uso de operaciones colectivas en MPI con un enfoque en las versiones que permiten un número variable de elementos por proceso. Se discuten diferentes modos de comunicación, incluyendo el envío y recepción de datos, así como las ventajas y desventajas del uso de buffering. También se tratan las comunicaciones no bloqueantes y cómo estas pueden ayudar a evitar deadlocks en la programación paralela.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Computación Paralela

Tema 3
MPI parte 3

Curso 2021/2022

Computación Paralela
1 / 35
N
Colectivas variables

Colectivas con número de elementos variables

Computación Paralela
2 / 35
N
Colectivas con número de elementos variable

I Varias operaciones colectivas tienen una versión que permite


definir para cada proceso un número de elementos diferente y
un desplazamiento dentro del buffer de envı́o/recepción.

I Varying count (V).

Operation Varying version


MPI Scatter MPI Scatterv
MPI Gather MPI Gatherv
MPI Allgather MPI Allgatherv
MPI Alltoall MPI Alltoallv

Computación Paralela
3 / 35
N
Colectivas con número de elementos variable

Ejemplo:
int MPI_Scatterv( void *sendbuf, int *sendcnts, int
*displs, MPI_Datatype sendtype, void *recvbuf,
int recvcnt, MPI_Datatype recvtype, int root,
MPI_Comm comm)

P0 A1 A2 A3 A4 A5 A6 A7 A8 A9 P0 A1
P1 A2 A3
P2 A6
displs 0 1 5 6 6
P3
cnts 1 2 1 0 3 P4 A7 A8 A9

Computación Paralela
4 / 35
N
Modos de comunicación

Diferentes tipos de comunicación y su protocolo.

Computación Paralela
5 / 35
N
Modos de comunicación

Dos conceptos:

I Modo de comunicación: Hace referencia al uso que se hace


de buffers internos en el envı́o y/o recepción.

I Comunicación no bloqueante: Comunicación que se ejecuta


en segundo plano, las funciones de envı́o/recepción retornan
inmediatamente y se usan más adelante otras funciones para
comprobar si la operación ha terminado o esperar a que
termine.

Computación Paralela
6 / 35
N
Envı́o y recepción

MPI_Send(data,5,MPI_INT,2,...) MPI_Recv(data,7,MPI_INT,1,...)

P1 P2
User User
memory memory

Network

Computación Paralela
7 / 35
N
Envı́o y recepción

MPI_Send(data,5,MPI_INT,2,...) MPI_Recv(data,7,MPI_INT,1,...)

P1 P2
User User
memory memory

Network

Computación Paralela
7 / 35
N
Envı́o y recepción

MPI_Send(data,5,MPI_INT,2,...) MPI_Recv(data,7,MPI_INT,1,...)

P1 P2
User User
memory memory

MPI lib MPI lib


memory memory

Network

Computación Paralela
7 / 35
N
Envı́o y recepción

MPI_Send(data,5,MPI_INT,2,...) MPI_Recv(data,7,MPI_INT,1,...)

P1 P2
User User
memory memory

MPI lib MPI lib


memory memory

Network

Computación Paralela
7 / 35
N
Envı́o y recepción

MPI_Send(data,5,MPI_INT,2,...) MPI_Recv(data,7,MPI_INT,1,...)

P1 P2
User User
memory memory

MPI lib MPI lib


memory memory

Network

Computación Paralela
7 / 35
N
Ventajas e inconvenientes de usar buffering

I Ventajas
I Agrupar mensajes pequeños mejora eficiencia.
I Permite realizar comunicaciones ası́ncronas (no bloqueantes).
I Reduce el tiempo de espera en envı́o.

I Inconvenientes
I Puede complicar/ralentizar el proceso de mensajes grandes.
I Incremento del uso de memoria.
I En la recepción se incrementa el tiempo de la comunicación
innecesariamente si el destino ya está esperando.

MPI permite controlar el buffering con los modos de comunicación.

Computación Paralela
8 / 35
N
Modos de comunicación

MPI define cuatro modos de envı́o y uno de recepción.


En general, la llamada a la función de envı́o termina cuando la
zona de datos que se envı́an puede volver a utilizarse.

I Buffered El usuario reserva su propio espacio para el buffer de


mensajes (MPI Buffer attach()).
I Synchronous El envı́o se bloquea hasta que se invoca en el
destino la operación de recepción correspondiente.
I Standard Es el modo por defecto. Puede utilizar buffer o ser
sı́ncrona. Depende de la implementación y las circunstancias.
I Ready Unicamente funciona si la operación de recepción ya
está activa.

Computación Paralela
9 / 35
N
Recv

I Solo hay un modo de recepción.

I La recepción se bloquea hasta que se recibe el mensaje.

I Al finalizar la función el cuerpo del mensaje se ha copiado a la


zona de memoria apuntada por el puntero data.

int MPI_Recv(void *data, int count, MPI_Datatype


datatype, int source, int tag, MPI_Comm comm,
MPI_Status *status)

Computación Paralela
10 / 35
N
Buffered send

I El usuario define su propio buffer

I Uso habitual: Cuando se conoce el volumen máximo de datos


a enviar (en una o más operaciones), el volumen es grande
(seguramente más que los bufferes internos de MPI), tenemos
memoria libre, no queremos que las ciertas operaciones Send
se bloqueen esperando a tener sitio en los bufferes de MPI
para copiar el mensaje, y queremos agilizar las copias al buffer.

I Operaciones: Se hace un alloc de memoria, se le indica a MPI


que use ese puntero como buffer

I Se utiliza una función de send especı́fica para que use ese


buffer

Computación Paralela
11 / 35
N
Buffered send
int MPI_Buffer_attach(void *buffer, int size)

int MPI_Bsend(void *data, int count, MPI_Datatype


datatype, int dest, int tag, MPI_Comm comm)

Computación Paralela
12 / 35
N
Buffered send
I MPI Bsend copia los datos al buffer.
I Cuando la función retorna los datos están en el buffer y los
datos originales o el puntero data ya se pueden modificar.
I El envı́o se realiza más adelante.

P1 P2

MPI_Bsend()
Buffer
MPI_Recv()
otherStuff()

Computación Paralela
13 / 35
N
Synchronous send
I Cuando el que envı́a no quiere continuar hasta estar seguro de
que el receptor ya está preparado para recibir.
int MPI_Ssend(void *data, int count, MPI_Datatype
datatype, int dest, int tag, MPI_Comm comm)

Computación Paralela
14 / 35
N
Synchronous send

I MPI Ssend se bloquea hasta que el destino ejecuta el recv.

P1 P2

MPI_Ssend()
MPI_Recv()

otherStuff()

Computación Paralela
15 / 35
N
Ready send
I Cuando no importa que se pierdan mensajes, sino maximiar la
eficiencia eliminando copias en bufferes innecesarias.
int MPI_Rsend(void *data, int count, MPI_Datatype
datatype, int dest, int tag, MPI_Comm comm)

Computación Paralela
16 / 35
N
Ready send
I Supone que el destino ya ha invocado el recv.
I Utiliza un protocolo más rápido.
I Si el mensaje llega antes de la recepción, se pierde.

P1 P2

MPI_Recv()
MPI_Rsend()

Computación Paralela
17 / 35
N
Default send

I El habitual, el que se utiliza por defecto


I Se ejecuta por MPI en uno de dos modos posibles

int MPI_Send(void *data, int count, MPI_Datatype


datatype, int dest, int tag, MPI_Comm comm)

Computación Paralela
18 / 35
N
Default send

I Puede ser synchronous o buffered.

I Depende de la implementación y la gestión interna de buffers.

I El buffer (en caso de utilizarlo) no lo define el usuario.

I Pueden aparecer deadlocks según la implementación, tamaño


de datos, etc.

I Los programas que usan default send deberı́an funcionar


correctamente para la implementación más restrictiva
(synchronous send).

I Suponer MPI Send = MPI Ssend.

Computación Paralela
19 / 35
N
Deadlock
I Bloqueo que se produce entre los diferentes procesos de una
comunicación cuando esperan la finalización de una
operación, que no puede ocurrir, para iniciar la siguiente.

I Dos tipos tı́picos en MPI:


I Blocking recv
I Synchronous send.

Computación Paralela
20 / 35
N
Deadlock tipo 1

int rank, size;


int data;
int tag = 0;

MPI_Init( &argc, &argv );


MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );

int dest = (rank +1 ) % size;


int source = (rank -1 + size) % size;

MPI_Recv(&data, 1, MPI_INT, source, tag, MPI_COMM_WORLD,


MPI_STATUS_IGNORE);
data = 123;
MPI_Send(&data, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);

Computación Paralela
21 / 35
N
Deadlock tipo 1

P1 P2

MPI_Recv()
MPI_Recv()

MPI_Send() MPI_Send()

Computación Paralela
22 / 35
N
Deadlock tipo 2

int rank, size;


int data = 123;
int tag = 0;

MPI_Init( &argc, &argv );


MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );

int dest = (rank +1 ) % size;


int source = (rank -1 + size) % size;

MPI_Send(&data, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);


MPI_Recv(&data, 1, MPI_INT, source, tag, MPI_COMM_WORLD,
MPI_STATUS_IGNORE);

Computación Paralela
23 / 35
N
¿Deadlock tipo 2?

P1 P2

MPI_Bsend()
MPI_Bsend()

MPI_Recv() MPI_Recv()

Computación Paralela
24 / 35
N
Deadlock tipo 2

P1 P2

MPI_Ssend()
MPI_Ssend()

MPI_Recv() MPI_Recv()

Computación Paralela
25 / 35
N
Comunicaciones no bloqueantes

Comunicaciones en dos fases, solapamiento de tareas y solución a


deadlocks.

Computación Paralela
26 / 35
N
Comunicaciones no bloqueantes
I Inician la comunicación pero las funciones retornan
inmediatamente, antes de que se complete.
I Permiten solapar comunicación y computación.
I Solución para los deadlocks.
I La llamada a la función puede terminar antes de que el
mensaje haya sido copiado al/desde el buffer.
I Para asegurar que la comunicación ha terminado se necesita
llamar a la función MPI Wait.
I Se pueden combinar envı́os bloqueantes/no bloqueantes con
recepciones bloqueantes/no bloqueantes.
I Estas funciones comienzan por MPI I*, (abreviatura de
Inmediato).

Computación Paralela
27 / 35
N
Nonblocking recv
Recepción: Se indica el mensaje que se espera recibir.
La función Wait espera a que el mensaje esté copiado en la
memoria indicada por el programador en el recv.

P1 P2

MPI_Irecv()

Recv data array


otherStuff() should not be
modified

MPI_Wait()
MPI_Send()

The message is
moreStuff() in the data array

Computación Paralela
28 / 35
N
Nonblocking send
Envı́o: Se indica el mensaje y destinatario.
La función Wait espera a que la zona de memoria pueda volver a
utilizarse. La semántica concreta depende del modo.

P1 P2

MPI_Isend()

Sent data array


otherStuff() should not be
modified

MPI_Wait()
MPI_Recv()
The data is in
the buffer or
moreStuff()
it has been
delivered

Computación Paralela
29 / 35
N
Modos y comunicaciones no bloqueantes

Modo Bloqueante No bloqueante


Buffered MPI Bsend MPI Ibsend
Synchronous MPI Ssend MPI Issend
Standard MPI Send MPI Isend
Ready MPI Rsend MPI Irsend
Recv MPI Recv MPI Irecv
Probe MPI Probe MPI Iprobe

Computación Paralela
30 / 35
N
Nonblocking send and recv

int MPI_Isend(void *data, int count, MPI_Datatype


datatype, int dest, int tag, MPI_Comm comm,
MPI_Request *request)

int MPI_Irecv(void *data, int count, MPI_Datatype


datatype, int source, int tag, MPI_Comm comm,
MPI_Request *request)

I MPI Request: Objeto con el estado de una operación no


bloqueante.

Computación Paralela
31 / 35
N
Finalización de comunicación

I MPI Wait: Espera hasta la finalización de una operación no


bloqueante.

int MPI_Wait(MPI_Request *request, MPI_Status *stat)

I MPI Test: Comprueba la finalización de una operación no


bloqueante. La variable flag toma el valor verdadero si ha
terminado.

int MPI_Test(MPI_Request *request, int *flag,


MPI_Status *status)

Computación Paralela
32 / 35
N
Solapar computación y comunicación

P1 P2 P1 P2

MPI_Isend()
MPI_Irecv()

otherStuff()
MPI_Send() MPI_Recv() otherStuff()
message message
transmision transmision
MPI_Wait() MPI_Wait()

Computación Paralela
33 / 35
N
Solución al deadlock

int rank, size;


int data_out = 123;
int data_in;
int tag = 0;

MPI_Init( &argc, &argv );


MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );

int dest = (rank +1 ) % size;


int source = (rank -1 + size) % size;
MPI_Request request;
MPI_Irecv(&data_in, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &request);

MPI_Send(&data_out, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);

MPI_Wait(&request, MPI_STATUS_IGNORE);

Computación Paralela
34 / 35
N
Otra solución al deadlock

int rank, size;


int data_out = 123;
int data_in;
int tag = 0;

MPI_Init( &argc, &argv );


MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );

int dest = (rank +1 ) % size;


int source = (rank -1 + size) % size;
MPI_Request request;
MPI_Isend(&data_out, 1, MPI_INT, dest, tag, MPI_COMM_WORLD, &request);

MPI_Recv(&data_in, 1, MPI_INT, source, tag, MPI_COMM_WORLD,


MPI_STATUS_IGNORE);

MPI_Wait(&request, MPI_STATUS_IGNORE);

Computación Paralela
35 / 35
N

También podría gustarte