Title: Titulo
1Titulo
Introducción a MPI Clase 3
Marcelo Rozenberg (agradecimiento Ruben Weht
ruweht_at_cnea.gov.ar)
2Ejemplo
Ejemplo Quiero calcular ?como
3Pi.f-1/2
double precision mypi, pi, h, sum, x, f,
a integer n, myid, size, i, rc, ierr,
status c --- funcion a integrar f(a) 4.d0
/ (1.d0 aa) c --- Numero de intervalos
read(5,) n c --- tamaño del intervalo h
1.0d0/n c --- realiza las sumas sum
0.0d0 do i 1, n x h (dble(i)
- 0.5d0) sum sum f(x) enddo
mypi h sum pimypi write(6,
'(" pi es aproximadamente", F18.16)') pi
end
4Pi.f-1/2
include 'mpif.h' double precision
mypi, pi, h, sum, x, f, a integer n, myid,
size, i, rc, ierr, status c --- funcion a
integrar f(a) 4.d0 / (1.d0 aa)
call MPI_INIT( ierr ) call MPI_COMM_RANK(
MPI_COMM_WORLD, myid, ierr ) call
MPI_COMM_SIZE( MPI_COMM_WORLD, size, ierr )
print , "Proceso ", myid, " de ", size, "
funcionando" if(myid.eq.0) then read(5,)
n endif if(myid.eq.0) then do
i1,size-1 call MPI_SEND(n,1,MPI_INTEGER,
i,1,MPI_COMM_WORLD,ierr) enddo else
call MPI_RECV(n,1,MPI_INTEGER,0,1,MPI_COMM_W
ORLD,status,ierr) endif h 1.0d0/n
5Pi.f-2/2
sum 0.0d0 do i myid1, n, size
x h (dble(i) - 0.5d0) sum
sum f(x) enddo mypi h sum
if(myid.eq.0) then pimypi do
i1,size-1 call MPI_RECV(mypi,1,MPI_DOUBLE
_PRECISION,MPI_ANY_SOURCE,MPI_ANY_TAG,
MPI_COMM_WORLD,status,ierr)
pipimypi enddo else call
MPI_SEND(mypi,1,MPI_DOUBLE_PRECISION,0,99,
MPI_COMM_WORLD,ierr) endif if (myid
.eq. 0) then write(6, '(" pi es
aproximadamente", F18.16)') pi endif
call MPI_FINALIZE(rc) end
6Pi.f-2/2
0
1
0
2
1
3
0
7
3
5
1
6
2
4
0
En log2(p) pasos comunique el dato a los p-1
procesos. Si p1024 gano un factor 10!
7Comm. Colectivos
Con las comunicaciones punto-a-punto puedo hacer
(casi) todo!!! aunque se necesitaría algo mejor
para hacerlo más sencillo...
Comunicaciones colectivas
Ejemplo Broadcast
Datos
Ao
Ao
Ao
Ao
Ao
Procesos
MPI_Bcast(datos, tamaño, tipo, origen, comm,
error)
8Broadcast
En nuestro ejemplo para calcular ?
if(myid.eq.0) then do i1,size-1
call MPI_SEND(n,1,MPI_INTEGER,i,1,MPI_CO
MM_WORLD,ierr) enddo else
call MPI_RECV(n,1,MPI_INTEGER,0,1,MPI_COMM_WO
RLD,status,ierr) endif
call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ie
rr)
9Reduce
A veces uno está interesado en calcular algo
globalmente. En nuestro ejemplo de ?, quisieramos
simplificar
! collect all the partial sums
if(myid.eq.0) then pi0.d0 do
i1,size-1 call MPI_RECV(mypi,1,MPI_DOU
BLE_PRECISION,MPI_ANY_SOURCE,,MPI_COMM_WORLD,statu
s,ierr) pipimypi enddo
else call MPI_SEND(mypi,1,MPI_DOUBLE_PREC
ISION,0,99,MPI_COMM_WORLD,ierr) endif
MPI_Reduce (mypi, pi, 1, MPI_DOUBLE_PRECISION,
MPI_SUM, 0, MPI_COMM_WORLD,ierr)
10Pi.f-2/2
include 'mpif.h' double precision
mypi, pi, h, sum, x, f, a integer n, myid,
size, i, rc, ierr, status f(a) 4.d0 /
(1.d0 aa) call MPI_INIT( ierr )
call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
call MPI_COMM_SIZE( MPI_COMM_WORLD, size,
ierr ) if(myid.eq.0) read(5,) n
call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ie
rr) h 1.0d0/n sum 0.0d0 do
i myid1, n,size x h (dble(i) -
0.5d0) sum sum f(x) enddo
mypi h sum call MPI_REDUCE gt
(mypi,pi,1,MPI_DOUBLE_PRECISION,MPI_SUM,0,
MPI_COMM_WORLD,ierr) if (myid .eq. 0)
write(6, '(" pi es aproximadamente", F18.16)')
pi call MPI_FINALIZE(rc) end
11Comunicaciones en más detalle
12Comunicaciones Punto a Punto más comunes
MPI_SEND(datos, tamaño, tipo_de_dato, destino,
tag, comm, ierror) Ej MPI_SEND(n,1,MPI_INTEGER,i
,1,MPI_COMM_WORLD,ierr) envia 1 numero entero
n al proceso i de comm_world MPI_SEND(a,5,MPI_R
EAL,4,1,MPI_COMM_WORLD,ierr) envia los 5 numeros
reales del vector a(5) al proceso 4 de
comm_world MPI_RECV(datos, tamaño,
tipo_de_dato, origen, tag, comm,
status,ierror) Ej MPI_RECV(n,1,MPI_INTEGER,0,1,M
PI_COMM_WORLD,status,ierr)
13Comunic. Punto a Punto 2
Para recordar MPI_SEND y MPI_RECV estándar son
bloqueantes!!
size es el tamaño de los datos threshold es el
espacio de buffer disponible
Cualquiera de las 2 Situaciones puede ocurrir
14Que pasa si el proceso 1 no esta listo para
recibir?
Supongamos que MPI_Send(n,0) MPI_Recv(n,1)
- P0 para y espera hasta que P1 le da el OK
- P0 guarda el dato en un buffer y continua y lo
envia luego cuando P1 le da el OK - El programa falla
15Comunic. Punto a Punto 3
3 variantes de Send (y Recv)
SincrónicoMPI_Ssend(.....) Permite hacer
programas seguros ya que no utiliza espacios de
buffer. Portabilidad del codigo.
Buffered MPI_Bsend(.....) S guarda en un buffer
el mensaje y lo envia cuando R lo pida. Hay que
reservar espacio de buffer con la rutina
MPI_Buffer_attach(....)
Ready MPI_Rsend(.....) Puede usarse cuando S
esta seguro que ya le enviaron el aviso que R
esta listo. Si R no estaba listo el
comportamiento esta indefinido y es un error de
programacion
16Comm. Colectivos 1
- Comunicaciones Colectivas
- Involucran comunicación coordinada dentro de un
grupo de procesos identificados por un
comunicador - (ej. MPI_comm_world)
- Todas las rutinas son bloqueantes
- No hay tags involucrados
17Comm. Colectivos 2
- Tres tipos de comunicaciones colectivas
- De sincronización
- De transferencia de datos
- De cálculo
1) Rutinas de sincronización call
MPI_Barrier(comm, ierror) Todos los procesos del
comunicador comm esperan al llegar a la barrera
hasta la llegada de todos. Luego continuan todos
al mismo tiempo.
18Broadcast
2) Rutinas de transferencia de datos Broadcast,
Gather, Gatherv, Scatter, ScattervAllgather,
Allgatherv, Alltoall, Alltoallv
Broadcast
Datos
Ao
Ao
Ao
Ao
Ao
Proces.
MPI_Bcast(datos, tamaño, tipo, origen, comm,
error)
19Broadcast ej.
En nuestro ejemplo para calcular ?
if(myid.eq.0) then do i1,size-1
call MPI_SEND(n,1,MPI_INTEGER,i,1,MPI_CO
MM_WORLD,ierr) enddo else
call MPI_RECV(n,1,MPI_INTEGER,0,1,MPI_COMM_WO
RLD,status,ierr) endif
call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ie
rr)
20Scatter/gather
Datos
Ao
A1
A2
A3
Ao A1 A2 A3
scatter
Proces.
gather
MPI_Scatter(datos-o, tam-o, tipo-o, datos-r,
tam-r, tipo-r, raíz, comm,
error)
MPI_Gather(datos-o, tam-o, tipo-o, datos-r,
tam-r, tipo-r, raíz,comm,
error)
21Ejemplo de gather
Ejemplo de MPI_Gather multiplicación de una
matriz por un vector CAB, A(100,00) B(100)
C(100) con 4 procesos
dimension aloc(25,100), b(100), cloc(25),
ctotal(100) integer root data root/0/ do
i1,25 cloc(i)0. do k1,100
cloc(i)cloc(i) aloc(i,k)b(k)
enddo enddo call MPI_GATHER(cloc, 25, MPI_REAL,
ctotal, 25, MPI_REAL, root,
MPI_COMM_WORLD, ierr)
Nota sólo root junta (recibe) los datos
22A
B
C
P0
Aloc
Cloc
P1
P2
P3
MPI_Gather
C
P0 (root)
23A
P0 (root)
P0
Aloc
P1
P2
P3
MPI_Scatter
P0 reparte (dispersa) la matriz A