Este documento resume los conceptos clave de la simulación paralela. Explica que los sistemas de eventos discretos, partículas y variables agregadas que siguen ecuaciones diferenciales ordinarias son comunes en simulaciones y pueden ser paralelizados. Describe cómo identificar dependencias de datos y flujo para determinar qué partes de un problema se pueden computar en paralelo, y métodos como la descomposición de dominio espacial para lograr paralelismo y localidad en la comunicación.
1. Programación y Computación
paralela (3)
Dependencia, Paralelismo
y Localidad
Glen D. Rodríguez R.
Basado en material de J. Demmel
1
2. Qué se puede y qué no se puede paralelizar?
• La suma de dos matrices es fácilmente paralelizable
+
• Pero se puede paralelizar esto? A=B+C
A=B+C D=A+E
D=A+E
A=B+C D=A+E
2
3. Dependencia de data
• Relación de dependencia: read after write
• X=……..
• Y=X+-*…………
• La operación j+1 no puede realizarse correctamente
hasta que la operación j se realice.
• Más formalmente, si hay 2 operaciones de orden i, j con
i>j, hay relación de dependencia si alguno de los
INPUTS de la oper.j es el OUTPUT de la oper.i
• Se puede achicar sus efectos:
• A=B+C
• D=A+E
• A=G+H
A=B+C
• Se puede reordenar
D=A+E A=G+H
3
4. Dependencia de data y de flujo
• Relación de bloqueo: write after read
• F=G+D
• G=H+I
• Si i>j, el output de la oper.j es el input de la oper.i
• Se puede solucionar usando variables auxiliares:
• AUX=G
• F=AUX+D
• G=H+I
• Dependencia de flujo: if A>B then C=D+E. Primero hay
que hacer la comparación antes de tocar C. Si antes
alguna operación modificaba A ó B, debe ser antes
tocar C.
• SI NO hay ninguna de estas dependencias, se puede
paralelizar “a lo bestia” y funcionará bien. Por que
entonces no hay carreras por la data localidad 4
5. Paralelismo y Localidad en Simulación
• Problemas físicos tienen paralelismo y localidad:
• Muchos objetos operan independientemente unos de otros.
• Los objetos generalmente dependen más de otros objetos
cercanos que de los lejanos.
• Dependencia en objetos lejanos se puede simplificar.
• Algunos modelos científicos pueden crear paralelismo:
• Cuando un problema continuo se discretiza, la dependencia en
el tiempo se limita a time steps cercanos.
• Efectos lejanos se pueden ignorar o aproximar.
• Puede haber paralelismo en varios niveles
• Ej.: varios circuitos se pueden simular a diferentes niveles,
desde el de todo un aparato, hasta los componentes básicos
individuales.
5
6. Algunas clases básicas de simulación
• Sistemas de eventos discretos:
• Ejs: “Game of Life,” circuitos lógicos.
• Sistemas de partículas:
• Ejs: bolas de billar, dispositivos
semiconductores, galaxias.
• Variables agregadas que dependen de param. continuos:
• EDOs, ej: simulación de circuitos (Spice),
estructuras mecánicas, cinética química.
• Variables continuas que dependen de param. continuos:
• EDPs, ej: calor, elasticidad, electrostática.
• Muchas simulaciones combinan varias técnicas.
6
7. Resumen
• Eventos discretos discreto
• Tiempo y espacio discretos
• Partículas
• Caso especial de sistema agregado
• Ec. Diferenciales ordinarias (EDOs)
• Sistemas agregados
• Entidades o posiciones discretas, tiempo continuo
• Ec. Diferenciales parciales (EDPs)
• Tiempo y espacio es continuo
• SE VERA EN OTRO CAPITULO
continuo
• Identificar problemas comunes y sus soluciones
7
9. Sistema de eventos discretos
• Sistemas se representan como:
• Conjunto finito de variables.
• El conjunto de todos los valores de las variables en cierto
momento es un “estado”.
• Cada variable se actualiza computando una función de
transición dependiendo de otras variables.
• Pueden ser:
• sincrónicos: en cada time step discreto, se evalúan las
funciones de transición; “state machine”.
• asincrónicos: las funciones se evalúan sólo si los inputs
cambian, basados en un “evento” en alguna parte del sistema;
“event driven simulation”.
• Ej: “game of life:”
• Autómatas Celulares
• Espacio se divide en celdas, hay reglas que gobiernan el
contenido de cada celda en cada time step.
9
10. Paralelismo en el “Game of Life”
• Simulación sincrónica
• Usa dos copias de la matriz (vieja y nueva).
• El valor en cada celda depende sólo de las 9 celdas (ella misma más los 8
vecinos) en la vieja matriz.
• Simulación en time steps– cada celda se actualiza en cada time step.
• Fácil de paralelizar dividiendo el dominio físico: Domain Decomposition
P1 P2 P3 Repetir
compute localmente para actualizar celdas
P4 P5 P6 barrier()
intercambiar info e estado con los vecinos
P7 P8 P9 Hasta terminar último time step
• Localidad se logra usando grandes matrices divididas entre
procesadores
• Solo los valores fronterizos entre procesadores se intercambian.
• Qué forma dar a los dominios?
10
11. Mallas regulares
• Suponer que el grafo es una malla nxn
• Que partición tiene menos comunicación?
• Minimizar comunicación en la malla ≡ minimizar
ratio “superficie a volúmen” de la partición
n*(p-1) 2*n*(p1/2 –1)
cruces de borde cruces de borde
11
12. Simulación sincrónica de circuitos
• Circuito es un grafo hecho de subcircuitos unidos por cables
• Simulación de componentes necesaria para interacciones por cable.
• Estructura de datos es irregular (grafo).
• Algoritmo paralelo es manejado por tiempo o síncrono:
• Evaluar todos los componentes cada time step
• Partición del grafo asigna subgrafos a procesadores
• Determina paralelismo y localidad.
• Intenta distribuir equitativamente subgrafos a procesadores (balance de
carga).
• Intenta minimizar cruces de borde (menos comunicación).
Cruces de borde = 6 Cruces de borde= 10 12
13. Simulación asincrónica
• Las sincrónicas pueden desperdiciar tiempo:
• Simulan y computan incluso cuando no hay cambios.
• Las asincrónicas simulan solo cuando un evento llega de
algún componente:
• No hay time steps, sino eventos individuales con time stamp.
• Ej: “Game of life” en estanqus poco conectados.
• Ej: circuitos con delays (eventos: puerta que cambian de valor).
• Ej: tráfico en la calle (eventos: carros cambiando carriles, etc.).
• Es más eficiente, pero más difícil de paralelizar
• En MPI, los eventos serían mensajes, Pero como se sabe cuando
ejecutar un “receive”?
13
15. Sistema de partículas
• Un sistema de partículas tiene:
• Un número finito de partículas
• Moviéndose en el espacio según las leyes de Newton
• Tiempo es continuo
• Ejemplos
• Estrellas en el espacio
• Haz de electrones
• Átomos en una molécula sufriendo fuerzas electrostáticas
• Neutrones en un reactor de fisión
• Carros en una autopista
15
16. Fuerzas en el Sistema
• La fuerza actuando en una partícula se puede subdividir
F = F_externa + F_cercana + F_lejana
• Externa
• Corrientes oceánicas en los peces
• Campo eléctrico externo en haz de electrones
• Cercana
• Predadores atraídos por los peces
• Bolas de billar chocando entre si
• Fuerzas de Van der Wals en fluidos (1/r^6)
• Lejana
• Peces se acercan al cardumen (1/r^2 )
• Gravedad, electrostática
• Fuerzas gobernadas por EDP elípticas
16
17. Paralelismo en F_externa
• El más simple
• Las fuerzas externas son independientes
• “trivialmente paralelo”
• Distribuir las partículas equitativamente entre
procesadores
• Cualquier forma es buena
• Localidad perfecta, no necesitamos comunicación
• Para cada partícula en un pocesador, aplicar la fuerza
externa
17
18. Paralelismo en F_cercana
• Hay interacción y por lo tanto se necesita comunicación.
• La fuerza puede epender de partículas dercanas:
• Ej: colisiones.
• Algoritmos simples son O(n2): chequear todos los pares para ver
si colisionan.
• Modelo paralelo usual es descomposición del dominio
físico:
• O(n/p) partículas por procesador si es equitativo.
18
19. Paralelismo en F_cercana
• Desafio 1: interacciones de partículas cerca de los
bordesde un procesador:
• Debe comunicarse esas variables a los procesadores vecinos.
• Bajo ratio volumen a superficie = poca comunicación.
• Usar cuadrados, no tiras
Comunicar partículas en el
borde
Necesita chequear
colisiones en los
bordes
19
20. Paralelismo en F_cercana
• Desafio 2: balance de carga, si las partículas se juntan:
• Estrellas, electrones.
• Dividir el espacio en formas no regulares.
• Que cada región tenga más o menos el mismo número de part.
• Quad-tree en 2D, oct-tree en 3D.
Ej: cada cuadrado
tiene a lo más 3
partículas
Ver: http://donar.umiacs.umd.edu/quadtree/points/prquad.html
20
21. Paralelismo en F_lejanas
• Involucrarían interacción todos contra todos = mucha
comunicación.
• Furza depende de otras partículas:
• Ejs: gravedad, proteínas
• Algoritmos simples son O(n2)
• Descomposición espacial por si sola no ayuda pues cada
partícula necesita “visitar” a las demás.
Rotar conjuntos de partículas.
• Mantiene los proc. ocupados
• Todos los procesadores ven a
todas las partículas
• Mejores algoritmos superan O(n2).
21
22. Métodos de Partícula-Malla
• Basados en aproximación:
• Sobreponer una malla regular.
• “Mover” partículas al punto de malla más cercano.
• Aprovechar el hecho que las f.lejanas satisfacen una EDP fácil de
resolver en una malla regular:
• FFT, multigrid
• Exactitud depende de la finura de la malla y la uniformidad de la
distribución de partículas.
1) Partículas se mueven a la
malla (scatter)
2) Se resuelva la malla
3) Fuerzas se interpolan a
las partículas (gather)
22
23. Descomposición de árboles
• Basados en aproximación
• Fuerzas lejanas simplificadas – como una sola partícula
grande.
• Usar árbol; cada nodo contiene una aproximación de sus hojas.
• O(n log n) ó O(n) en vez de O(n2).
• Varios algoritmos
• Barnes-Hut.
• Fast multipole method (FMM)
de Greengard/Rohklin.
• Método de Anderson
23
25. Sistemas de Variables agregadas
• Muchos sistemas se pueden aproximar por:
• Sistema de vars. “agregadas” o macro variables.
• Dependen de un parámetro continuo (tiempo).
• Ej -- circuito:
• Se aproxima como grafo.
• Cables son las aristas.
• Nodos son las conexiones entre 2 o más cables.
• Cada arista tiene resistencia, capacitancia, inductancia y/o fuente de
voltaje.
• Sistema es “agregado” por que no se computa V o I en cada
punto del espacio, sino en la arista, o en los nodos.
• Ley de Ohm, de Kirchoff, etc.
• Forma un sistema de Ec. Diferenciales ordinarias (EDOs).
• Diferenciales con respecto a tiempo
25
26. Ejemplo de Circuito
• Estado de sistema representado por
• vn(t) Voltaje de los nodos
• ib(t) corriente de las aristas en el tiempo t
• vb(t) voltaje de las aristas
• Ecuaciones:
• Corriente de Kirchoff 0 A 0 vn 0
• Voltaje de Kirchoff A’ 0 -I * ib = S
• Ohm 0 R -I vb 0
• Capacitancia 0 -I C*d/dt 0
• Inductancia 0 L*d/dt I 0
• A es matriz dispersa, representa las coenxiones del
circuito
• Un gran sistema de EDOs (tal vez con restricciones
extra). 26
27. Ej.: análisis de estructuras
• Análisis de estructuras en ing. civil:
• Variables: desplazamiento de puntos en un edificio, columna.
• Leyes de Newton y de Hook (“resortes”).
• Modelo estático: ejercer fuerza y determinar desplazamiento.
• Modelo dinámico: aplicar fuerza continua (terremoto).
• Problema de Eigenvalue: modos resonantes del edificio vs el
terremoto
27
28. Resolviendo EDOs
• En estos ejemplos, las matrices son dispersas:
• O sea, la mayor parte de elementos son cero.
• Esos 0’s no se deben guardar ni computar.
• Disperso, por que cada componente solo depende de algunos
otros
• Dado un conjunto de EDOs, hay dos preguntas:
• Computar los valores de variables en un tiempo t
• Métodos explícitos
• Métodos implícitos
• Computar modos de vibración
• Problemas de Eigenvalue
28
29. Resolviendo EDOs : Métodos explícitos
• Asumir x’(t) = f(x) = A*x(t), donde A es una matriz dispersa
• Computar x(i*dt) = x[i]
para i=0,1,2,…
• EDO da x’(i*dt) = pendiente
x[i+1]=x[i] + dt*pendiente
Usar pendiente en x[i]
t (i) t+dt (i+1)
• Métodos explícitos, (Forward) Euler.
• Aproximar x’(t)=A*x(t) con (x[i+1] - x[i] )/dt = A*x[i].
• x[i+1] = x[i]+dt*A*x[i], o sea. Multp. matriz dispersa x vector .
• Sus más y sus menos:
• Algoritmo sencillo y paralelizable: multp. matriz vector.
• Problemas de estabilidad: se necesitar a veces dt muy
pequeño, sobre todo si el sistema es rígido (i.e. A tiene
elementos grandes x puede variar muy rápido).
29
30. Resolviendo EDOs: Métodos implícitos
• Asumir x’(t) = f(x) = A*x(t) , con A matriz dispersa
• Computar x(i*dt) = x[i]
para i=0,1,2,…
• EDOda x’((i+1)*dt) = pendiente
x[i+1]=x[i] + dt*pendiente
Usar pendiente en x[i+1]
t t+dt
• Método implícito, Backward Euler:
• Aproximar x’(t)=A*x(t) con (x[i+1] - x[i] )/dt = A*x[i+1].
• (I - dt*A)*x[i+1] = x[i], o sea se necesita resolver un sistema de
ecuaciones disperso.
• Sus más y sus menos:
• “dt” puede ser mayor: sobretodo para problemas rígidos
• Algoritmo más difícil: solución de ecuaciones dispersa
30
31. Resolviendo EDOs : Eigensolvers
• Computar modos de vibración: encontrar los
eigenvalues y eigenvectors.
• Buscar solución de x’’(t) = A*x(t) de forma
x(t) = sin(ω*t) * x0, donde x0 es un vector constante.
• Reemplazando, -ω2 *x0 = A*x0, así que –ω2 es un
eigenvalue y x0 es un eigenvector de A.
• Métodos de solución se reducen a multiplicación d
matrices dispersas, o a resolver sistemas de
ecuaciones dispersas.
31
32. EDOs y matrices dispersas
• Todos los problemas se reducen a operaciones con
dispersas:
• Explícito: multipl. Matriz dispersa x vector (SpMV).
• Implícito: sistema lineal disperso
• Soluciones directas (Eliminación Gaussiana).
• Soluciones iterativas (usan SpMV).
• Eigenvalues.
32
33. Hechos claves sobre SpMV
• y = y + A*x con A dispersa
• Escoger estructura de datos para A
• Compressed sparse row (CSR): popular para As genéricas en
procesadores con cache
• CSR: 3 arrays:
• col_index: ïndex de la columna de los valores no-zeros
• values: valores No-zero
• row_ptr: para cada fila, el index en el array col_index/values
for i = 1:m
start = row_ptr(i);
end = row_ptr(i + 1);
for j = start : end - 1
y(i) = y(i) + values(j) * x(col_index(j));
33
34. SpMV paralelo
• y = A*x, con A dispersa de tamaño n x n
x
P1
y P2
• Preguntas i: [j1,v1], [j2,v2],…
• En qué procesador guardar P3
• y[i], x[i], A[i,j]
• Donde computar P4
• y[i] = sum (from 1 to n) A[i,j] * x[j]
= (row i of A) * x … producto escalar disperso
• Particionar: Puede necesitar
• Cjto.de index de Partición {1,…,n} = N1 ∪ N2 ∪ … ∪ Np. comunicación
• For all i en Nk, proc. k guarda y[i], x[i], fila i de A
• For all i en Nk, proc. k computa y[i] = (row i of A) * x
• Regla “el dueño computa” : Proc. k computa las y[i] que posee.
34
35. “Los 7 enanos”
• “Problemas tipo” en cuanto a la computación y
comunicación necesaria
1. Álgebra lineal densa
2. Álgebra linear dispersa
3. Métodos espectrales, FFT
4. Métodos de N-cuerpos
5. Mallas estructuradas
6. Mallas no estructuradas
7. Montecarlo
35
37. MPI (Message Passing Interface)
• Es una interfaz estándar (1993) para la programación
usando el paradigma de paso de mensajes.
• Sirve tanto para grandes computadores de memoria
compartida, como para clusters o redes de
ordenadores heterogéneos (incluido el grid computing).
• Definida para C, C++ y FORTRAN.
• Comprende una gran cantidad de funciones (128),
macros, etc.
• Pero con 6 funciones básicas se puede empezar a
programar usando MPI.
37
38. Implementaciones de MPI
• Existen bastantes implementaciones del estándar MPI.
Algunas son debidas a proveedores de hardware que
las proporcionan (optimizadas) paras sus máquinas
(IBM, HP, SGI…), otras son desarrolladas en el ámbito
académico.
• Algunas implementaciones son:
• MPICH (MPICH 2 implementa MPI2)
• Disponible para múltiples devices incluido globus2.
• LAM/MPI
• OpenMPI unión de varios proyectos (FT-MPI, LA-MPI,
LAM/MPI, y PACX-MPI) .
38
39. Uso de MPI
• Se puede usar MPI para:
• Programas paralelos “portables”.
• Librerías paralelas.
• Programas con relaciones entre datos irregulares o dinámicas
que no se ajusten a un modelo de paralelismo en los datos.
• Cuando no usar MPI:
• Si se puede usar HPF o un programa paralelo Fortran 90.
• Si se pueden usar librerías de más alto nivel (que pueden
haber sido escritas usando MPI).
• Si no se necesita realmente el paralelismo ☺
39
40. MPI tipos de datos
• Se definen los siguientes tipos de datos MPI:
• MPI_CHAR
• MPI_SHORT
• MPI_INT
• MPI_LONG
• MPI_UNSIGNED_CHAR
• MPI_UNSIGNED_SHORT
• MPI_UNSIGNED
• MPI_UNSIGNED_LONG
• MPI_FLOAT
• MPI_DOUBLE
• MPI_LONG_DOUBLE
• MPI_BYTE
• MPI_PACKED
• Corresponde a los de C, pero se añaden el tipo byte, y el
empaquetado, que permite enviar simultáneamente datos de
distintos tipos.
40
41. MPI Funciones básicas
• Funciones básicas:
• MPI_Init => Inicialización de MPI.
• MPI_Finalize => Termina MPI.
• MPI_Comm_size => Para averiguar el número de procesos.
• MPI_Comm_rank => Identifica el proceso.
• MPI_Send => Envía un mensaje.
• MPI_Recv => Recibe un mensaje.
• Referencia del estándar en
• http://www-unix.mcs.anl.gov/mpi/
41
42. MPICH
• MPICH es una implementación gratuita de MPI 1.2
• Implementa parte del nuevo estándar MPI-2
• MPICH 2 implementa MPI-2
• Es una implementación muy “portable”:
• Supercomputadores de memoria distribuida
• Sistemas de memoria compartida
• Clusters
• Grid
• Esta se puede compilar para distintos “devices” de comunicación.
Consideraremos dos:
• MPICH-P4
• Device ch-p4 dirigido a redes de ordenadores.
• MPICH-G2
• Es una implementación “grid” de MPICH mediante el device globus2
• Completamente rediseñada desde la anterior versión MPICH-G
• http://www3.niu.edu/mpi/
42
43. Escribiendo programas MPI
• De las seis funciones básicas que mencionamos antes
MPI_Init y MPI_Finalize son imprescindibles para que
haya un programa MPI.
• Veamos un ejemplo trivial
#include "mpi.h"
#include <stdio.h>
int main( int argc, char **argv )
{
MPI_Init( &argc, &argv );
printf( "Hola Mundon" );
MPI_Finalize();
return 0;
}
43
44. Programas MPI (compilación)
• El programa anterior solo inicializa y termina el entorno
MPI. Entre tanto cada proceso imprime un mensaje
por pantalla.
• Para un programa pequeño como este podemos hacer
una llamada directamente al comando de compilación:
• mpicc (para programas C)
• mpif77 (Fortran 77).
• mpif90 (Fortran 90)
• mpiCC (C++)
• Para aplicaciones más complicadas conviene usar un
Makefile.
• En nuestro caso anterior (fichero hello.c):
mpicc –o hello hello.c
44
45. Ejecución de un programa MPI con MPICH
• El comando mpirun se usa para ejecutar los programas
MPI en MPICH. (esto no es parte del estándar)
• mpirun admite diversas opciones. Destacaremos las
siguientes:
• -np N: N indica el número de procesos que se quiere en la
ejecución del programa.
• -p4pg pgfile: indica explícitamente las máquinas en las que se
quiere correr y el path del programa y usuario que se usará en
cada una de ellas.
• -machinesfile mfile: fichero de máquinas para correr en lugar
del estándar (se usa en combinación con –np).
• Digamos que queremos correr nuestro programa en
dos máquinas de la lista estándar:
mpirun -np 2 hello
45
47. Delimitación del alcance de la comunicación
• Grupos separados de subprocesos trabajando en diferentes
subprogramas.
• Invocación paralela de librerías paralelas:
• Los mensajes propios de la aplicación deben mantenerse separados
de los de la librería.
• MPI proporciona grupos de procesos
• Inicialmente el grupo “all”.
• Se proporcionan rutinas para la administración de los grupos.
• Todas las comunicaciones, no solo las colectivas, tienen lugar en
grupos.
• Un grupo (group) y un contexto (context) se combinan en un
comunicador (communicator).
• Fuente y destino en una operación send o receive se refieren al rank
en el grupo asociado con un comunicador dado. Se puede usar
MPI_ANY_SOURCE en una operación receive.
47
48. MPI tipos de comunicación
• La comunicación MPI entre procesos puede ser de dos
tipos:
• Punto a punto: el proceso “origen” conoce el identificador del
proceso “destino” y envía un mensaje dirigido solo a él. Se
usan las funciones MPI_Send y MPI_Recv.
• Colectiva: Operaciones en las que participan todos los
procesos de un operador. Ejemplo:
• “Broadcast”: El proceso origen manda el mensaje a todos los
demas (que pertenezcan al mismo comunicador). Esto es típico
de un esquema “master-slave”. Se usa la función MPI_Bcast.
• Las funciones MPI de recepción de datos son por lo
general “bloqueantes”, es decir, un proceso que debe
recibir un mensaje espera hasta que de hecho lo ha
recibido completo.
48
49. Obteniendo información de MPI
• Usaremos ahora dos más de las seis funciones
básicas: MPI_Comm_size y MPI_Comm_rank.
• Así averiguaremos desde el programa el número de
procesos que participan y la identificación de cada uno.
int main( argc, argv )
{
int rank, size;
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );
printf( “Hola Mundo! Soy el proceso %d de %dn", rank, size );
MPI_Finalize();
return 0;
}
49
50. Funciones de comunicación MPI
• A continuación veremos un
poco más en detalle las
funciones básicas de envío y
recepción de mensajes punto
a punto y broadcast.
• MPI_Send
• MPI_Recv
• MPI_Bcast
• MPI_Reduce
50
51. Sintaxis de MPI_Send y MPI_Recv
• La operación básica de envío (bloqueante) es:
MPI_Send( start, count, datatype, dest, tag, comm )
1. start: puntero a los datos a enviar
2. count: número de elementos a enviar
3. datatype: tipo de dato
4. dest: Identificación del proceso destino
5. tag: etiqueta de la comunicación
6. comm: Identificación del comunicador
• La operación básica de recepción correspondiente:
MPI_Recv(start, count, datatype, source, tag, comm, status)
1. start: puntero para la recepción de los datos
2. count: número de elementos
3. datatype: tipo de dato
4. source: Identificación del proceso origen
5. tag: etiqueta de la comunicación
6. comm: Identificación del comunicador
7. status: puntero para acceso a información sobre mensaje
51
52. Ejemplo MPI_Send/MPI_Recv
char msg[100];
if(my_rank==0)
{
sprintf(msg,"nnt Esto es un mensaje del proceso %d al proceso
%d",source,dest);
MPI_Send(msg,100,MPI_CHAR,dest,TAG,MPI_COMM_WORLD);
printf("n Mensaje enviado a %d",dest);
}
else if(my_rank==1)
{
MPI_Recv(msg,100,MPI_CHAR,source,TAG,MPI_COMM_WORLD,&status);
printf("n Mensaje recibido en %d",dest);
printf(msg);
}
52
53. Adquiriendo información sobre un mensaje
• MPI_TAG y MPI_SOURCE son usados principalmente cuando
hay MPI_ANY_TAG y/o MPI_ANY_SOURCE en la llamada
MPI_Recv.
• MPI_Get_count se usa para determinar la cantidad de datos de
un tipo dado que se han recibido.
MPI_Status status;
MPI_Recv( ..., &status );
... status.MPI_TAG;
... status.MPI_SOURCE;
MPI_Get_count( &status, datatype, &count );
53
54. Operaciones colectivas
• Comunicación colectiva: envío de un mensaje de uno
a muchos. Se hace con MPI_Bcast (Broadcast)
• Típicamente un master envía los mismos datos a sus
esclavos.
• Por ejemplo, en la paralelización del entrenamiento de una
red neuronal enviamos a todos los esclavos los nuevos
pesos al final de cada época de entrenamiento.
• Operaciones colectivas: se realiza una operación
matemática distribuida y se devuelve el resultado al
root de la operación
• También es típico en un esquema master-slave.
• En la neura se utiliza por ejemplo en la suma de los errores
de todos los esclavos.
• Operaciones definidas:
• Aritméticas: suma, multiplicación…
• Lógicas: AND, OR…
54
56. Reduce
• MPI_MAX maximum integer, float integer, real, complex
• MPI_MIN minimum integer, float integer, real, complex MPI_SUM
sum integer, float integer, real, complex
• MPI_PROD product integer, float integer, real, complex
• MPI_LAND logical AND integer logical
• MPI_BAND bit-wise AND integer, MPI_BYTE integer, MPI_BYTE
• MPI_LOR logical OR integer logical
• MPI_BOR bit-wise OR integer, MPI_BYTE integer, MPI_BYTE
• MPI_LXOR logical XOR integer logical
• MPI_BXOR bit-wise XOR integer, MPI_BYTE integer, MPI_BYTE
• MPI_MAXLOC max value and location float, double and long
double real, complex,double precision
• MPI_MINLOC min value and location float, double and long double
real, complex, double precision
56
57. Sintaxis de Broadcast y Reduce
• Broadcast:
MPI_Bcast(start, count, datatype, root, comm)
1. start: puntero a los datos a enviar
2. count: número de elementos a enviar
3. datatype: tipo de dato
4. root: identificación del proceso origen
5. comm: Identificación del comunicador
• Reduce:
MPI_Reduce(start, result, count, datatype, operation, root, comm)
1. start: puntero a los datos a enviar
2. result: puntero para almacenar el resultado
3. count: número de elementos a enviar
4. datatype: tipo de dato
5. operation: identificación de la operación colectiva
6. root: identificación del proceso origen
7. comm: Identificación del comunicador
57
58. Reduce
• Operaciones predefinidas para MPI_Reduce:
• MPI_MAX máximo
• MPI_MIN mínimo
• MPI_SUM suma
• MPI_PROD producto
• MPI_LAND “and” lógico
• MPI_LOR “or” lógico
• MPI_LXOR “xor” lógico
• MPI_BAND “bitwise and”
• MPI_BOR “bitwise or”
• MPI_BXOR “bitwise xor”
• MPI_MAXLOC máximo e índice del máximo
• MPI_MINLOC mínimo e índice del mínimo
• Además existe un mecanismo para que el usuario cree sus
propias funciones para el “Reduce”.
58
59. Ejemplo BroadCast
Char msg[100];
if(my_rank==source)
{
sprintf(msg,"n Esto es un mensaje del proceso %d a todos los demás",sourc
e);
MPI_Bcast(msg,100,MPI_CHAR,source,MPI_COMM_WORLD);
printf("n Mensaje enviado a todos desde %d",source);
}
else
{
MPI_Bcast(msg,100,MPI_CHAR,source,MPI_COMM_WORLD);
printf("n Mensaje recibido en %d desde %d",my_rank,source);
printf(msg);
}
59
60. Ejemplo Reduce
int value;
int result;
value = my_rank;
MPI_Reduce(&value,&result,1,MPI_INT,MPI_SUM,source,MPI_COMM_WORLD);
if(my_rank==source)
{
printf("n Resultado de la suma colectiva %d", result);
}
60
61. Integración en paralelo
#include <stdio.h>
#include <math.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
int nprocs, myproc;
int i, n;
double pi_25= 3.141592653589793238462643;
double pi, w, x, y, error;
double t0, t1;
/* MPI initialization */
MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &nprocs );
MPI_Comm_rank( MPI_COMM_WORLD, &myproc );
/* Determine the number of divisions to use */
if( argc == 2 ) { /* Take n from the command line argument */
sscanf( argv[1], "%d", &n );
} else {
n = 1000; /* Otherwise use 1000 divisions */
}
if( myproc == 0 ) printf("Calculating pi using %d divisionsn", n);
61
/* Broadcast the number of divisions to all nodes */
62. Sigue el programa
MPI_Bcast( &n, 1, MPI_INT, 0, MPI_COMM_WORLD); /* ??? Is this needed ??? */
/* Start the timer after a barrier command */
MPI_Barrier( MPI_COMM_WORLD );
t0 = MPI_Wtime();
pi = 0.0;
w = 1.0 / n;
/* Each processor starts at a different value and computes its
* own contributions to pi. */
for( i=myproc; i<n; i+=nprocs ) {
x = (double) i / n;
y = sqrt( 1.0 - x*x );
pi += y * w;
}
MPI_Allreduce( &pi, &pi, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );
pi = pi*4;
error = fabs( pi - pi_25 );
t1 = MPI_Wtime();
if( myproc == 0 ) {
printf("The calculated pi = %f (error = %f)n", pi, error);
printf("The calculation took %f seconds on %d nodesn", t1-t0, nprocs);
}
MPI_Finalize(); 62
}