Introducción a la progamación en paralelo

Enrique Lomba Instituto de Química Física Rocasolano, CSIC

Programa MOSSNOHO-CM, 7-8 Febrero 2007, Madrid

Esquema
⇨ ⇨
⇨ ⇨

Modelos computacionales paralelos El estandard MPI
Basic Linear Algebra Comunication System (BLACS) Scalable Linear Algebra PACKage (ScaLAPACK)

Modelos de computación

Paralelismo de datos (CRAY 1), arquitectura SIMD (Single Instruction Multiple Data). Tambien en nuevos procesadores (PIV, alpha) Memoria compartida (Shared Memory), en equipos con varios procesadores (Symmetric MultiProcessors = SMP)
M e m o ria R A M

P ro c 1

P ro c 2

P ro c 3

‰

Programación con hebras (threads)
¾ ¾

High Performance Fortran (HPF) OpenMP (Chandra et al., Parallel Programming in OpenMP, AP)

o

o

Toda la memoria es compartida (las variables pueden ser comunes a todas las hebras) Un programa puede tener varias hebras. En cada hebra:
¾ ¾

Programme counter (instrucción a ejecutar) Stack (almacenamiento intermedio)

Paso de mensajes. (Message Passing)
● ●

Message Passing Interface (MPI) Parallel Virtual Machine (PVM)

RAM

RAM

RAM

P1 P2

P3

POSIX threads. OpenMP. se establece intercomunicación.● Cada proceso (/ador) tiene su propia memoria. ✔ Participación activa de todos los procesos en la comunicación ¾ ¾ Envío de datos (en proceso emisor) Recepción de datos (en proceso receptor) ⇨ Operaciones remotas de memoria ● Acceso a la memoria de otro proceso sin su participación ✔ ✔ ✔ Típico en CRAY T3E Nuevo estandard MPI-2 Nuevo estandard de arquitectura: Virtual Interface Arquitecture (VIA) ⇨ Creación dinámica de procesos ● ● PVM. MPI-2 Ausente en MPI-1 .

⇨ Los modelos de computación se adaptan a un hardware específico Cualquier modelo de computación es compatible con cualquier hardware por emulación de software (a costa de la eficiencia) Hidra y Ladon ⇨ .

Ethernet 1Gb/s Myrinet 2Gb/s Hardware en LADON .

⇨ ⇨ LADON es un cluster de memoria distributida (DMP) El modelo de paralelismo más adecuado es el de paso de mensajes (MPI-1). En su momento con operaciones en memoria remota (MPI-2) Communication protocol TCP/IP Logical device MPI application Ch/p4 Mx/Gm shm Communication Device (network card. shared memory) MX/GM Threads .

Se accede desde programas en C. C++ o Fortran) BLACS: subrutinas de comunication alto nivel en Fortran. ScaLAPACK: Librería Fortran de Algebra Lineal. MPI-1: construido sobre MX (C.Niveles de Software en LADON ⇨ MX library: específica de Myrinet (alto rendimiento). construida sobre BLACS. Paso de mensajes con operaciones en memoria remota. ⇨ ⇨ ⇨ . Construido sobre MPI.

) ⇨ ⇨ Cada proceso tiene su espacio de memoria asignado Comunicación = copia de una porción de memoria de un proceso a otro: operación cooperativa . Diferentes implementaciones ✔ ✔ LAM (Notre Dame University) MPICH (Argonne National Lab. Version 1.Message Passing Interface ⇨ ⇨ Es una especificación (conjunto de subrutinas).2.

device Non RAM buffered communication Node 1 Node 2 ⇨ MPI implementa la comunicación con tres niveles de buffering ● ● ● Buffer RAM explícito : MPI_BSEND Buffer en dispositivo (implícito): MPI_SEND Sin buffer : (MPI_SSEND) .RAM buffer RAM Buffered communication RAM buffer Process 2 Device buffer Device buffer Process 1 Comm. device Comm.

⇨ Argumentos mínimos de una subrutina ● Sender ✔ ✔ ✔ Datos (primera posición de memoria+longitud) Proceso de destino Identificación de datos (tag) Primera posición de memoria + longitud donde se almacenarán los datos Variable en la que se almacena el identificador del proceso que envía los datos.length.length.source.tag.destination.actual_length) . ● Receiver ✔ ✔ ● ● send(address.tag) receive(address.

⇨ Tipos de datos en MPI ● ● ● ● ● ● MPI_INTEGER MPI_REAL MPI_DOUBLE_PRECISION MPI_COMPLEX MPI_LOGICAL MPI_CHARACTER .

A (1 ) A (4 ) A (7 ) ⇨ ⇨ ⇨ ⇨ Descripción de datos en envío ● (address.datatype) Ej.3.MPI_REAL) Los tipos de datos MPI son genéricos La identificación tag permite la recepción ordenada de los mensajes Los procesos se identifican por rango (rank) de 0 a N-1 (N procesos) .count. (A.

⇨ MPI define además ● ● contexto: conjunto de procesos y variables involucrados en un cálculo grupo: Procesos involucrados en una parte del calculo ⇨ context+group = communicator: se identifican por una variable entera. Se evita recurrir a los tags (y posibles interferencias con subrutinas de librerías internas) .

⇨ Inicialización en información ● MPI_Init(ierr) ✔ Integer : ierr Integer : com.ier) = ¿Quien soy? ✔ com =MPI_COMM_WORLD ● MPI_Comm_size(com.np.my_rank. my_rank.ierr) ¿Cuantos procesos tengo ? ✔ Integer: np .ier ➢ ● MPI_Comm_rank(com.

⇨ Comunicación punto a punto ● MPI_Send(mess.tag.com.tag.ierror Integer status(MPI_STATUS_SIZE) En MPI_Send parcial.tag.cont.ierror ● MPI_Recv(mess.com.datatyp.cont.ierror) ✔ Integer cont.com.source.source.dest. hasta recepción de datos ● Comunicación con bloqueo ✔ ✔ .datatyp.status.i error) ✔ ✔ Integer cont. hasta disponibilidad de buffer En MPI_Recv total.dest.data.com.data.tag.

● MPI_Barrier(comm.datatyp.root.comm.ierror) ✔ Integer root (identifica proceso que envia los datos) Sincroniza procesos Todos los procesos envian datos a root que los recoje ordenadamente por rango Root envia datos (un vector) a todos los procesos.count.ierror) ✔ ● MPI_Gather (MPI_AllGather) ✔ ● MPI_Scatter (MPI_AllScatter) ✔ ● Bloqueo total . Cada proceso recibe una porción del vector por orden de rango.⇨ Comunicación colectiva ● MPI_Bcast(mess.

Esquema de comunicación colectiva .

result. root. MPI_MINLOC Operaciones definidas por el usuario (avanzado) ✔ Operación colectiva sobre los operand almacenando el resultado en result ● ● Bloqueo total MPI_AllReduce ✔ Retorna el resultado a todos los procesos dentro del comunicador . datatyp. op. count. MPI_MIN MPI_SUM. comm. MPI_PROD MPI_MAXLOC. ierror) ✔ ✔ <tipo> operand(*).⇨ Computación colectiva ● MPI_Reduce(operand. result(*) Integer OP = ● ● ● ● MPI_MAX.

• Ejemplo de Programa: Cálculo de π ∞ 1 π=∫ dx 2 1+ x 0 π = h ∑ f ( xi + h / 2) i=0 N .

f. 'pi is '.0d0/n sum = 0.MPI_COMM_WORLD. numprocs x = h * (dble(i) . n.h" double precision PI25DT parameter (PI25DT = 3. numprocs.0.MPI_DOUBLE_PRECISION. myid.*) n endif c broadcast n call MPI_BCAST(n.MPI_INTEGER. 0 ) then print *.pi. abs(pi . h. i. ierr c function to integrate f(a) = 4.0. myid.program main include "mpif. 0 ) goto 30 c calculate the interval size h = 1. ' Error is'. & MPI_COMM_WORLD.ierr) c node 0 prints the answer. ierr) 10 if ( myid .5d0) sum = sum + f(x) 20 continue mypi = h * sum c collect all the partial sums call MPI_REDUCE(mypi. 0) then print *.141592653589793238462643d0) double precision mypi. pi. 'Enter the number of intervals: (0 quits) ' read(*.eq. ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD. numprocs.PI25DT) endif goto 10 30 call MPI_FINALIZE(ierr) stop end .0. pi. a integer n. sum. x. if (myid .le.eq.MPI_SUM.d0 + a*a) call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD.1.d0 / (1.1.ierr) c check for quit signal if ( n .0d0 do 20 i = myid+1.

⇨ Prototipo de algoritmo paralelo: Master-slave (self-scheduling) ● El master distribuye tareas entre los esclavos y recoge los resultados ⇨ Ejemplo: Matriz x vector G G c = Ab n j=1 ci = ∑ Aijbj .

ierr) numsent = numsent+1 else ! Tell sender that there is no more work call MPI_SEND(MPI_BOTTOM. i. cols.lt. MPI_DOUBLE_PRECISION. & sender. MPI_DOUBLE_PRECISION. numsent+1. rows) then ! send another row do 50 j = 1. MPI_ANY_TAG. MPI_COMM_WORLD. ierr) c send a row to each slave process.min(numprocs-1.j) 30 continue call MPI_SEND(buffer. MPI_COMM_WORLD. cols. 0. ierr) numsent = numsent+1 40 continue do 70 i = 1. MPI_COMM_WORLD. cols. 1.Código del master numsent = 0 send b to each slave process call MPI_BCAST(b. & MPI_ANY_SOURCE. MPI_DOUBLE_PRECISION.rows call MPI_RECV(ans. MPI_DOUBLE_PRECISION. 0. & sender. Ierr) c endif 70 continue . & MPI_COMM_WORLD. & i. & MPI_COMM_WORLD.j) 50 continue call MPI_SEND(buffer. master. status.cols buffer(j) = a(i. MPI_DOUBLE_PRECISION.cols buffer(j) = a(numsent+1. ierr) sender = status(MPI_SOURCE) anstype = status(MPI_TAG) ! row is tag value c(anstype) = ans if (numsent . tag with row number do 40 i = 1.rows) do 30 j = 1.

MPI_ANY_TAG. rows) goto 200 call MPI_RECV(buffer. status. 1.cols ans = ans+buffer(i)*b(i) continue call MPI_SEND(ans. ierr) go to 90 endif continue 100 & 200 .0 do 100 i = 1. cols. MPI_COMM_WORLD. 0) then go to 200 else row = status(MPI_TAG) ans = 0. master. MPI_COMM_WORLD.eq. cols. MPI_COMM_WORLD. ierr) if (status(MPI_TAG) . MPI_DOUBLE_PRECISION. ierr) skip if more processes than work if (rank .Código de los esclavos c c & c & 90 & slaves receive b.gt. MPI_DOUBLE_PRECISION. row. MPI_DOUBLE_PRECISION. master. then compute dot products until done message received call MPI_BCAST(b. master.

Escalado • Nº de operaciones: n(n+n-1) • Nº de transmisiones: n(n+1) ( n + n )Tcom Tcom Eficiencia = lim = 2 n → ∞ (2 n − n )T 2Top op 2 .

ierr) ¾ Integer color. newcom. ierr (los procesos con color=0 forman un nuevo comunicador. y se ordenan según el valor de key) . key. color. newcom.Uso de los comunicadores ⇨ ⇨ ⇨ ● Permiten restringir la comunicación a un grupo de procesos (con características determinadas) MPI_COMM_WORLD (integer) = todos los procesos Creación de comunicadores MPI_COMM_SPLIT (MPI_COMM_WORLD. key.

color.key. ' Enter itest ?' Read(*.MPI_INTEGER.MPI_INTEGER. ierr) key = 0 ! ! Separate processes with even numbers from those with odd numbers ! in communicators newcom and newcom1 ! color = Mod(myid.color1.itest. 'Comunicador nuevo: itest ='.ierr) ! broadcast to odd processes Call MPI_BCAST(itest.Eq.key.0. ierr) Call MPI_COMM_SIZE(MPI_COMM_WORLD.MPI_COMM_WORLD.0.0.' in process '.*)itest ! broadcast to even processes Call MPI_BCAST(itest.Eq.Ejemplo de uso de comunicadores Call MPI_COMM_RANK(MPI_COMM_WORLD.1) itest = -50 ! create communicator newcom (even processes) Call MPI_COMM_SPLIT(MPI_COMM_WORLD.newcom1.newcom.ierr) Print *.' in process '.1. myid Else Call MPI_BCAST(itest.MPI_INTEGER.ierr) ! create communicator newcom1 (odd processes) Call MPI_COMM_SPLIT(MPI_COMM_WORLD. numprocs.0.ierr) Print *. myid.' in process '.newcom.0) Then Print *.2) color1 = Mod(myid+1.1. ' Enter itest again ?' Read(*.1.*) itest Endif Call MPI_BCAST(itest.newcom1.ierr) If (myid.MPI_INTEGER.newcom. myid Call MPI_FINALIZE(ierr) End Program comunicador .1.Eq. ' itest ='.0) Then Print *. 'Comunicador nuevo: itest ='.itest.2) If (myid.ierr) Print *.itest. myid End If If (myid.

Cálculo de π por Monte Carlo • Algoritmo: 4 N in π = N total .

⇨ ⇨ ⇨ Servidor: genera y despacha números aleatorios a los clientes Clientes: determinan aproximaciones parciales a π y las suman Podría haber más de un servidor: Intercomunicador Intracomunicador clientes Intracomunicador servidores .

⇨ Código del servidor request = 1 Do While (request > 0) ! ! receive request from workers ! Call MPI_RECV(request.MPI_COMM_WORLD.ierr) If (request > 0) Then ! ! Send random numbers ! Call Random_number(rand(1:size)) Call MPI_SEND(rand.size.status.MPI_ANY_TAG& &.1.MPI_COMM_WORLD.ierr) End If End Do .reply_tag.MPI_ANY_SOURCE.MPI_INTEGER.MPI_DOUBLE_PRECISION& &.status(MPI_SOURCE).

ierr) ! ! receive random numbers ! Call MPI_RECV(rand.size.status.⇨ Código de los clientes Do While (.request_tag& &.MPI_DOUBLE_PRECISION.size-1. MPI_SUM. MPI_INTEGER.MPI_COMM_WORLD. totalout.MPI_COMM_WORLD.& & workers.0d0*Dble(totalin))/Dble(totalin + totalout) .reply_tag& &.& & workers. 1. totalin.ierr) Pi= (4.ierr) Call MPI_ALLREDUCE(out.1. done) ! ! send request for work ! Call MPI_SEND(request.0d0) Then out = out+1 Else in = in+1 End If End Do ! ! get results from all workers and add them ! Call MPI_ALLREDUCE(in.ierr) Do i=1.server. 1.MPI_INTEGER. MPI_INTEGER.server.Not.2 x = 2*rand(i)-1 y = 2*rand(i+1)-1 If (x*x+y*y > 1. MPI_SUM.

Tipos de datos derivados en MPI ⇨ Permiten la transmisión eficiente de datos no contiguos en memoria y de datos estructurados ● Typemap = {(tipo0.g.…(tipon-1.despn-1)} Real*8 Real*8 Character*1 0 ⇨ 8 16 17 Los datos han de estar alineados en los límites adecuados (e. los real*8 con desplazamientos absolutos múltiplos de 8 bytes) .desp0).

ierror) Integer count. extent. oldtype. stride. ierror Utilidades ‰MPI_type_extent(datatype.stride. blocklengths(count).newtype. extent. blocklength. oldtype.oldtypes. newtype.blocklength. ierror ‰MPI_type_free(datatype) .newtype.Definición de nuevos tipos ⇨ ⇨ ⇨ ● MPI_type_vector(count.oldtype. newtype. ierror) MPI_type_struct(count. blocklengths.ierror) MPI_type_contiguous(count. ierror): Longitud de un tipo ‰MPI_type_commit(datatype): Materialización del tipo oInteger datatype.offsets. oldtypes(count).

• Matrices NrowsΧ Ncols en memoria (sólo Fortran) Elementos contiguos ⎛ a11 ⎜ a ⎜ 21 ⎜a ⎝ 31 a12 a22 a32 a13 ⎞ ⎟ a23 ⎟ ⎟ a33 ⎠ Elementos separados por Nrows .

0) Then Write(*.Nmol) End Do forces(:.MPI_DOUBLE_PRECISION. One element contails Nmol dp ! values separated by a Nmol stride in the original matrix ! Call MPI_TYPE_VECTOR(Nmol.Ne.1.5).MPI_COMM_WORLD. ".'(/"* Column broadcast: forces matrix in proc.ierr) .j=1.1).Enviando columnas y filas de matrices ! ! Broadcast of columns (Fortran coding only) ! Call MPI_BCAST(Forces(1.Nmol.i2/40("-"))')myid Do i=1.MPI_DOUBLE_PRECISION.4)')(Forces(i.ierr) ! Broadcast one element of rowtype (Nmol values) Call MPI_BCAST(Forces(2. Nmol Write(*.Nmol.ierr) Call MPI_TYPE_COMMIT(rowtype.0.:) = 0 End If ! ! Define new type of strided type. & &MPI_COMM_WORLD.ierr) If (myid.rowtype.rowtype.'(10f18.1.j).0.

ierr) Envio de datos estructurados . ext_int.types.0. ierr) ! ! define blockcounts and displacements ! blockcount(0) = ndim*3+1 blockcount(1) = 1 blockcount(2) = 4 displ(0) = 0 displ(1) = 10*extent displ(2) = displ(1)+ext_int ! ! define old types inside the structure ! types(0) = MPI_DOUBLE_PRECISION types(1) = MPI_INTEGER types(2) = MPI_CHARACTER ! ! commit the structure ! Call MPI_TYPE_STRUCT(3.. ierr) Call MPI_TYPE_EXTENT( MPI_CHARACTER.Nmol. ! ! determine the extent of various types involved in the calculations ! Call MPI_TYPE_EXTENT(MPI_DOUBLE_PRECISION.ierr) Call MPI_TYPE_COMMIT(particletype.particletype.ierr) ! Broadcast array of struct Call MPI_BCAST(Moleculas. ext_char.Type Molec Sequence Real(kind=8) :: r(ndim) Real(kind=8) :: v(ndim) Real(kind=8) :: a(ndim) Real(kind=8) :: mass Integer :: count Character. extent.blockcount. Allocatable :: Moleculas …….MPI_COMM_WORLD. Dimension(4) :: nombre*1 End Type Molec Type (Molec).particletype. ierr) Call MPI_TYPE_EXTENT(MPI_INTEGER. Dimension(:).displ.

mp). El proceso 0 es vecino del proceso 1 y del proceso Np .(0..Np) Bidimensional : Cartesiana (0...g..(0..(np.mp) Tridimensional ● ● El sistema operativo gestiona la distribución óptima de acuerdo al hardware Las mallas pueden ser periódicas: e.0).⇨ Topologías virtuales ● Ordenamiento virtual de los procesos en una malla (grid) ✔ ✔ ✔ Monodimensional (0.(np.1).0)..

4) 4 8 12 (4.4) 1 5 9 16 13 .Malla periódica cartesiana en 2D 13 4 1 8 9 16 5 9 13 (0.0) 14 2 6 10 14 15 3 7 11 15 16 (0.

isperiodic. ier) Integer coords(Ndim) ⇨ ● MPI_CART_COORDS(comNd. reorder. dims. Ndim. Ndim. Ndim. isperiodic. Ndims. ierr ) Integer numprocs ⇨ ● MPI_CART_GET( commNd. isperiodic(Ndim) ⇨ ● MPI_DIMS_CREATE( numprocs. rank. dims. coords. dims(Ndim). coords. Ndim. ierr ) ● ● Integer oldcomm. commNd. ier) Integer rank .Funciones básicas ⇨ MPI_CART_CREATE(oldcomm. commNd. ierr Logical reorder. dims.

dest. dest.2) P15(3..¿Cómo identificar a los vecinos ? P1(0.Ndim-1.2) P5(0.0) P15(3. source. source. direction=0.2) P4(1. shift.2) P11(2.3) Malla cartesiana no periódica MPI_CART_SHIFT(comm. Ausencia de vecinos: la comunicación con el proceso MPI_PROC_NULL no se ejecuta (i.0) P2(2.3) P12(2.0) ⇨ ● P0(0. direction.3) P14(3.1) P6(1.0) P7(1.1) P9(2. ierr ⇨ MPI_PROC_NULL.1) P13(3.1) P3(0.3) P8(1.e. no consume recursos) Útil en algoritmos en los que un proceso hace de tubería de datos (data pipeline) ⇨ .. shift. ierr) Integer comm.

.. y ) u ( x. j + uik.. y ) = f ( x. i = 0. j +1 + uik. j ) 4 ... n + 1 n +1 u k +1 i. y ) ⇐ x = 1/ y = 1 ui −1. j − h 2 f i . j −1 + ui +1. j h 2 = fi .. y ) = g ( x. j +1 + ui . j − 4ui . j + ui .. j Algoritmo iterativo de Jacobi 1 k = (ui −1. i = 0.Ecuación de Poisson: método de Jacobi ∇ 2 u ( x. j i xi = . j −1 + uik+1. n + 1 n +1 j yj = ..

Intercambio de datos entre procesos (matrix uij distribuida) Ghost points for processes other than P0 Ghost points for P0 P0 Internal zone .

. 5. 3. 4. Determinar procesos vecinos Intercambio de ghost points entre procesos vecinos Iteración de las ecuaciones de Jacobi (local) Comprobar convergencia (global) Volver a 4 si no hay convergencia 2.y) entre los procesos de la malla de cálculo. Construcción de una malla cartesiana 2D de procesos (no periódica) Distribuir la malla de NxN puntos (x. 6. 7.Esquema de iteración 1.

1. ierr ) MPI_Cart_shift( comm2d. nbrleft. nbrbottom. ierr ) . nbrright. "strided" datatype for the exchange in the "non-contiguous" ! direction (up/down) ! MPI_Type_vector( ey-sy+1. 1. 1.MPI_DOUBLE_PRECISION. ex-sx+3. stride. ierr ) MPI_Type_commit( stride. ierr ) Creación de un tipo de datos para transmisión de filas ! ! Create a new. 1.Determinación de vecinos MPI_Cart_shift( comm2d. 0. nbrtop.

stridetype. comm2d. & nbrright. 1. ierr ) call MPI_SENDRECV( a(sx. MPI_DOUBLE_PRECISION.sy). & a(ex+1. recvcount. 1. 0. 0. MPI_DOUBLE_PRECISION. status. 1. nbrtop. nx. status. recvcount. nx. recvbuf(*) . status. except for less data call MPI_SENDRECV( a(sx. 1.sx + 1 c These are just like the 1-d versions. status. sendtag. 1. ierr •<type> sendbuf(*). & nbrright. sendtype. stridetype.sy-1). recvtag. & comm2d. nbrbottom.sy). ierr ) call MPI_SENDRECV( a(sx. nx. & comm2d. & a(sx. dest. ierr ) c c This uses the vector datatype stridetype call MPI_SENDRECV( a(ex. 0. status. recvbuf. stridetype. ierr ) ‰ MPI_SENDRECV(sendbuf. dest. sendcount.ey). 1. status(MPI_STATUS_SIZE). nx.Intercambio de datos nx = ex . rectype. nbrtop. stridetype.ey+1). & a(sx. sendtag. sendtype. recvtype. 0. ierr) • integer sendcount. comm.sy). 1. MPI_DOUBLE_PRECISION. comm2d.sy). nbrbottom. & nbrleft. & a(sx-1. & nbrleft. 1.sy). MPI_DOUBLE_PRECISION. comm. recvtag.

count. status(MPI_STATUS_SIZE. status. request. ierr) Integer src ⇨ ● ● MPI_TEST(request. ierr ⇨ ● MPI_IRECV(buf. ierr) Integer status(MPI_STATUS_SIZE) Logical flag ⇨ ● MPI_WAITALL(count. datatype. request. tag. ierr) <type> buf(*) Integer count.Solapamiento de comunicación y cálculo: comunicación sin bloqueo (asíncrona) ⇨ ● ● MPI_ISEND(buf. datatype. array_of_requests. comm. dest. comm. flag. count. tag. comm. nrqst) ⇨ MPI_WAIT. MPI_WAITANY . ierr) Integer array_of_requests(nrqst). datatype. dest. array_of_status. request. src. tag.

⇨ ⇨ MPI_ISEND MPI_IRECV Envío y recepción de ghost points (sin bloqueo) Iteración sobre zona interna ⇨ ⇨ MPI_WAITALL (Bloqueo hasta finalización de la comunicación) Iteración sobre ghost points .

1997) •On-line tutorial http://www.html .⇨ ⇨ La comunicación asíncrona es la más eficiente No todo el hardware la soporta •Bibliografía •Using MPI.msi. 1999) •Parallel Programming with MPI.edu/tutorial/scicomp/general/index.Lusk & Skjellum (MIT Press. Gropp. Pacheco (MK.umn.

npcol.nprow.pnum.errornum) blacs_gridexit(icntxt) .nprow.nprocs) blacs_gridinfo(icntxt.Basic Linear Algebra Comunication System ⇨ ⇨ Define una malla de procesos Componentes ● Subrutinas de incialización e información ✔ ✔ ✔ ✔ ✔ ✔ ✔ blacs_gridinit(icntxt.order.npcol) (order='r'.mypcol) Integer function blacs_pnum(icntxt.'c') blacs_pinfo(mypnum.prow.pcol) blacs_abort(icntxt.prow.pcol) blacs_pcoord(icntxt.nyprow.

double complex) XX=(GE..D.) ¾ ¾ ¾ v= (I.suma) . maximo).complex.matriz trapezoidal) YY= (SD. (BR. (RV..Z) --(Integer.'A') (sincronización) Call vGZZZ2D(.matriz rectangular) (TR.) ➢ ZZZ = (AMX.scope) (scope='R'.✔ blacs_exit(icontinue) ⇨ Comunicación basada en matrices ● ● Comunicación punto a punto (send/receive) Broadcast ✔ Call vXXYY2D(.. send).minimo).S.C. double. single.(SUM.'C'.(AMN. broadcast receive) ● Operaciones colectivas ✔ ✔ blacs_barrier(icntxt.. receive. BS(Broadcast send).

ScaLAPACK ⇨ ⇨ ⇨ Subrutinas de alto nivel para álgebra lineal Comunicación basada en BLACS Esencial : Las matrices han de estar distribuidas en los procesadores de forma eficiente ● Distribución no cíclica (ineficiente) 1234 5678 9 10 11 12 13 14 15 16 P1 P2 P3 P4 .

Bloque nb=2) 1 2 9 10 3 4 11 12 5 6 13 14 7 8 15 16 P1 P2 P3 P4 .● Distribución cíclica por bloques (e.g.

nrhs.n).n) (m.irscr.desca.i. B(LDB.llda.nb.nrhs) ˜l= A x b ˜l ● ● Call dgesv(n.icscr) coordenadas del proceso a partir del que se empieza la distribución -normalmente (0.descb.desb ● ● ● llda=dimensión local de A en cada proceso (ircsr.IPIV.LDA.info) ✔ ✔ ⇨ Descriptores de matrices distribuidas : desca.nrhs.icntxt.j).A.B.I.info) (ScaLapack) Inicialización de descriptor (integer descx(9)) (en todos los procesos) Dimension A(m.IPIV.A(i.info) (Lapack) (normalmente i=j=1) Call pdgesv(n.n. .1.1).icscr.n) dimensión globlal Call descinit(desca.m.LDB.B(I.mb.⇨ Lapack vs ScaLapack : A(LDA.0)-.j.

⇨ Cálculo de llda para A(M.mp) = llda ⇨ ⇨ .myrow.isr.mb.mycol.isc.isc) no_cols = numroc(N.N) en una malla de tamaño mp x np con una distribucion en bloques de mb x nb desde el proceso (isr.np) no_rows = numroc(M.nb.

Ejemplo •Diagonalización de una matriz simétrica distribuida por columnas usando Scalapack .exe prueba_mpi.1 serial proporcionadas por Intel.f90 -lmkl_scalapack -lmkl_blacsF77init -lmkl_blacs -lmkl_blacsCinit -lmkl_lapack -lmkl_em64t Se emplea la librerías MathKernel 7.Instrucciones de compilación ⇨ ⇨ mpif90 -o prueba_mpi.2 de cluster junto con las MathKernel 8.