Paradigmas de Computación Paralela, Concurrente y Distribuida

Anuncio
Paradigmas de Computación
Paralela, Concurrente y
Distribuida
Dra. Veronica Gil-Costa
e-mail: gvcosta@unsl.edu.ar
ggvcosta@gmail.com
Bibliografía
•
O. Bonorden et all - PUB library, Release 6.0 - User guide and function reference. 1998.
•
O. Bonorden et all - The Puderborn University BSP (PUB) Library- Desing, Implementation and
performance. 1999.
•
M. Goudreau et all - Towards Efficiency and Portability: Programming with the BSP model. 1996.
•
J. Keller et all - Practical PRAM programming. John Wiley & Sons inc.. 2001.
•
C. Leopold - Parallel and Distributed Computing: A survey of models, paradigms, and approaches.
2001.
•
W.F. Mccoll - BSP Programming. 1994.
•
M. Quinn - Parallel Computing. Theory and Practice. Second Edition. McGraw-Hill. Inc. 1994.
•
L.G. Valiant - A Bridging Model for Parallel Computation. 1990.
•
General Purpose parallel Architectures. 1990.
•
B. Wilkinson, et all - Parallel Programming: Tecniques and Aplications using Networked
Workstations and Parallel Computers. 1999.
Modelo de Computación Secuencial
Computadora von Neumann
Clock
CPU
Memoria de
Programa
Cómo se escriben los programas?
Memoria
RAM
..
Mi
..
M1
M0
ALU
Registros
Contador de Programa
Qué es la computación paralela?
Tradicionalmente el soft. se escribe
en forma serial
Es el uso simultáneo de múltiples
recursos de cómputos para resolver un
problema
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
ARPANET
1969
1976 1987
1990
1993
1995
1999
2005
2007
tiempo
ARPANET
Primera red de computadoras
básico
Experimento militar
Comienzo de la Internet
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
ARPANET
Cray-1
1969
1976 1987
1990
1993
1995
1999
2005
2007
tiempo
Cray-1
Procesamiento vectorial: Usa la misma instrucción
para realizar la misma operación sobre varios
argumentos
150millones de operaciones por segundo de punto
flotante
Computadores grandes, costosos
Dueños: Universidades, gobierno, grandes
industrias.
Usuarios experimentados (tarjetas perforadas)
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
prototipo Parallel
Inference Machine
(PIM)
ARPANET
Cray-1
1969
1976 1987
1990
1993
1995
1999
2005
2007
tiempo
Computación Paralela
Popular a fines de los ’80 principios
de los ’90
Primera Crisis
Problema: el software limitado a la
investigación y la milicia
Los lenguajes de alto nivel para el
modelo de Von- Neumann: C y
Fortran
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
prototipo Parallel
Inference Machine
(PIM)
Redes de Comp.
ARPANET
Cray-1
1969
1976 1987
NOW
1990
1993
Beowulf
1995
1999
2005
2007
tiempo
Redes de Computadoras
NOW: proyecto de la Universidad de Bekeley
Primer cluster de computadoras más poderoso del
mundo
Beowulf: es un estilo de cluster diseñado para
realizar cálculos paralelos HPC
Tenía 16 computadores personales Intel 200MHz
conectados por medio de un switch Ethernet
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
prototipo Parallel
Inference Machine
(PIM)
Redes de Comp.
ARPANET
Cray-1
1969
1976 1987
NOW
1990
1993
GRID
Beowulf
1995
1999
2005
2007
Hacer del poder computacional tan fácil como la red eléctrica
Proyecto SETI: Globus Toolkit
tiempo
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
prototipo Parallel
Inference Machine
(PIM)
Redes de Comp.
ARPANET
PVM
Cray-1
1969
1976 1987
MPI
NOW
1990
1993
GRID
Beowulf
1995
1999
OpenMP
Multi-core
2005
2007
tiempo
Línea Temporal
Línea Temporal
Top 500 http://www.top500.org/lists/2010/11
229376 GB
186368 Cores
Intel EM64T Xeon X56xx
(Westmere-EP) 2930 MHz (11.72
GFlops)
Noviembre 2010
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
prototipo Parallel
Inference Machine
(PIM)
Redes de Comp.
ARPANET
PVM
Cray-1
1969
1976 1987
MPI
NOW
1990
1993
GRID
Beowulf
1995
1999
OpenMP
Cloud
Multi-core Comp.
2005
2007
tiempo
Cloud Computing
Es un paradigma que ofrece servicios a través de
internet.
Los usuarios acceden sin conocimiento de la
gestión de internet
Utilizan cachés temporales de clientes (equipos de
escritorio, portátiles, etc.).
A pesar de que las capacidades de las PC han
mejorado, gran parte de su potencial se
desperdicia
Línea Temporal
Sist. Paralelos
Sist. Distribuidos
Sist. Hibridos
prototipo Parallel
Inference Machine
(PIM)
Redes de Comp.
ARPANET
PVM
Cray-1
1969
1976 1987
MPI
NOW
1990
1993
GRID
Beowulf
1995
1999
GPU
OpenMP
Cloud
Multi-core Comp.
2005
2007
tiempo
GPU
Descienden de los chips gráficos de finales de los
’80.
Usualmente no tenían soporte para dibujo de
figuras.
La velocidad de las CPU de la década del ’90 no
permitieron implementar GPUs más avanzados
Popularidad reciente: alta especialización de las
GPU para cáclulo con valores de punto flotantes
(gráficos 3D)
Computación Paralela
Características del problema
Aplicaciones
Por qué usar computación Paralela?
Computación Paralela:
Características del problema
Se puede dividir en partes discretas de trabajo
que se pueden resolver simultáneamente
Ejecutar múltiples instrucciones de programa en
cualquier instante de tiempo
Se resuelve en menos tiempo con múltiples
recursos que con uno sólo
Aplicaciones
Sistema de predicción del tiempo
Superficie de USA + Candada = 20.000.000 Km2
Altitud de 20 km
20 M Km2 * 20 Km = 400 M km3
….
4 * 1013 cálculos computacionales para predecir 1 hs.
Si queremos saber la predicción de 2 días y con un procesador
se ejecuta 1 billón de cálculos por seg
4 * 1013 * 48 horas = 2 * 1015 cálculos
2 * 1015 cal./ 109 calc. por seg. = 2 * 106 seg. = 23 días!!!
Aplicaciones
Calcular las orbitas planetarias y
galácticas
Movimiento de las placas tectónicas
¿Qué tienen estas aplicaciones en común?
Tráfico de vehículos en horas extremas
Operaciones de mercado (bancos,
Se
caracterizan por requerir el procesamiento de una
economía)
gran cantidad de información en forma rápida
Explotación de petróleo
Por qué usar Computación Paralela?
Razones principales:
Ahorrar tiempo
Resolver grandes problemas
OtrasParalela
razones:
LaComp.
es la evolución de la computación
secuencial
que intenta
emular
lo que sucede
en el
Aprovechar
el uso
de recursos
no locales
mundo real, donde varios eventos
Ahorrar costos: usar varias computadoras
complejos e interrelacionados suceden simultáneamente
económicas
Evitar problemas de memoria
Paradigmas de Computación
Paralela, Concurrente y
Distribuida
Introducción a los Sistemas Paralelos
Terminología
Tarea: programa o un conjunto de
instrucciones (tipo-programa) que
se ejecuta en un procesador.
Paradigmas de computación Paralelas
Computación Concurrente
Es la simultaneidad en la ejecución de múltiples
tareas interactivas. Es la base de la Comp. Paralela.
Son tareas que se ejecutan en el mismo instante.
Es una colección de procesos o hilos secuenciales
que se ejecutan (lógicamente) en paralelo.
Pseudo-paralelismo: cuando las tareas se ejecutan
en una máquina secuencial.
Como se puede implementar la
concurrencia?
Multiprogramación:
Multiprocesamiento:
Los threads multiplexan su ejecución sobre
una máquina secuencial
Los threads multiplexan su ejecución sobre
multicores o multiprocesadores
Procesamiento distribuido:
Los procesos multiplexan su ejecución sobre
diferentes máquinas
Coherencia y seguridad
Si los threads acceden a recursos
compartidos se logra seguridad si:
Todos los accesos no tienen efecto
sobre los recursos (ej. variables)
Sólo un acceso a la vez
(exclusión mutua)
Problema de “Too much milk”
Tiempo
Tu
3:00
Llegas a casa
3:05
Miras en la heladera
no hay leche
Vas al mercado
3:10
3:15
compañero de cuarto
Llega a casa
3:20
Llegas al mercado
Mira la heladera, no hay leche
Hay que SINCRONIZAR y actualizar datos correctamente
3:25
Compras la leche
Va al mercado
3:30
3:35
3:45
Llegas a casa
Pones en la heladera
Llega al mercado
Compra la leche
Llega a casa, Oh! No!!!
Problema: “filósofos cenando”
Hay 5 filósofos sentados en una mesa
redonda
Entre cada filósofo hay un chopstick.
Cada filósofo hace dos cosas: pensar y
comer
El filósofo piensa por un rato
Cuando tiene hambre
Agarra el chopstick derecho e izquierdo
No puede comer sin los 2 chopstick, sino espera
Cuando termina de comer libera los chopstick.
Problemas: Competencia, coherencia y seguridad por los recursos
semáforos, mutex, etc.
Paradigmas de computación Paralelas
Computación Paralela vs.
Computación Distribuida
Divide una aplicación en tareas que se
ejecutan al mismo tiempo
Divide una aplicación en tareas que se
ejecutan usando diferentes recursos
Paradigmas de computación Paralelas
Computación Paralela
vs.
Computación Distribuida
diferentes
recursos
Divide una aplicación en tareas Utiliza
físicamente separados
que se ejecutan simultáneamente
(fuertemente acoplado)
Se consideran varias aplicaciones
Se considera una aplicación por a la vez (pueden pertenecer a
diferentes usuarios).
vez.
Objetivo: acelerar la ejecución de Objetivo: permitir que varios
usuarios
trabajen
en
forma
una aplicación
cooperativa
Se ejecutan sobre arquitecturas Se ejecutan sobre arquitecturas
abiertas
y
homogéneas
con
memoria heterogéneas,
dinámicas
compartida
Sistema Distribuido
Cada procesador tiene su propia memoria: La
dirección de memoria de un procesador no mapea
en otro procesador (no hay direcciones globales a
través de los procesadores).
Cada procesador opera independientemente
El acceso a los datos de otro procesador lo define
explícitamente el usuario (pasaje de mjes, sync.,
etc.)
Sistema Distribuido
Ventajas:
Memoria escala con el número de procesadores
Cada procesador accede a su propia memoria
sin interferencia ni overhead causado por
mantener la coherencia de la memoria
Desventajas:
El programador es responsable de la
comunicación
Difícil mapear datos basados en memoria
global
Paradigmas de computación Paralelas
Sin embargo tienen muchas características en común:
Múltiples procesadores
Los procesadores están interconectados por alguna
red
Múltiples procesos están en progreso al mismo
tiempo y cooperan unos con otros
Paradigmas de computación Paralelas
Multiplicación de un vector por una
matriz un procesador
0
1
0
x
1
2
3
2
Si para cada resultado 5 t. 4
5
6
5
7
8
9
8
Total 15 t. en 1 procesador
Multiplicación de un vector por una
matriz varios procesadores
0
1
0
x
0*1+1*2+0*3
Proc0
1
2
3
4
5
6
0*4+1*5+0*6
Proc1
7
8
9
0*7+1*8+0*9
Proc2
Si para cada resultado 5 t. Total 5 t. en 3 procesadores
Terminología
Tarea Paralela: se ejecuta en varios
procesadores en forma segura
(resultados correctos).
Terminología
Comunicación:
A través de pasaje de mensajes
A través de memoria compartida
Acceso a memoria remota
Sincronización:
Coordinación de tareas paralelas en tiempo
real.
Terminología
El tamaño de un proceso puede ser
descrito por su granularidad
TAMAÑO DE COMPUTACIÓN ENTRE DOS
PUNTOS CONSECUTIVOS DE
COMUNIACIÓN Y SINCRONIZACIÓN
Terminología
Granularidad gruesa:
Comunicación y sincronización
Cómputo
Comunicación y sincronización
Mucho computo. Mas oportunidad para mejorar la performance.
Terminología
Granularidad fina:
Comunicación y sincronización
Cómputo
Comunicación y sincronización
Cómputo
Comunicación y sincronización
Cómputo
Comunicación y sincronización
Más overhead de comunicación.
Menos oportunidad para mejorar la performance.
Granularidad
Como métrica de granularidad se
puede utilizar una relación entre
computación y comunicación:
Granularidad = Tcomp/Tcomm
Aumentar la granularidad:
• Reduce los costos de creación de procesos y
comunicación entre procesos
• Reduce el número de procesos concurrentes y la
cantidad de paralelismo
Terminología
Speed-up: aceleración del código paralelo respecto
del código secuencial
speed-up( P ) T1/ T(P)
Speed-up
Super-lineal
Speed-up lineal
Speed-up típico
Numero de procesadores P
Eficiencia: se define como el ratio entre el speed-up
y el número de procesadores
Ef( P ) = speed-up(P)/P
Limites del Paralelismo
No todos los programas son
fácilmente paralelizables
Los programas tienen una parte
secuencial y una parte paralelizable
Parte secuencial
Dependencia de datos?
Parte paralela
a = b + c;
d = a + 1;
e = d + a;
for (i=0; i < e; i++)
M[i] = 1;
Ley Amadahl’s
Todo cómputo posee una porción
serial “s” que no puede ser
paralelizable. Sin importar la
cantidad de procesadores P que se
utilicen, el tiempo de ejecución no
puede ser menor que “s”.
Tpo secuencial
f
No se puede paralelizar:
Límite de la mejora que se
puede obtener
Ley Amadahl’s
tiempo
Usando 5 procesadores para el
trabajo paralelo
25 seg.
+
50 seg.
+
25 seg.
100 seg.
secuencial
paralelo
25 seg.
secuencial
+
10 seg.
25 seg.
secuencial
secuencial
60 seg.
Speed- up = Tsec/Tpar
= 100 seg./ 60 seg. = 1.67
Administración de tareas
Overhead agregado por la
administración de un conjunto de tareas
Overhead: Tiempo requerido para
coordinar las tareas paralelas (opuesto al
hacer trabajo útil)
Tiempo de Start-up
Sincronización
Comunicación de datos
Software overhead, threads,
Tiempo de finalización de las tareas
Balance de carga
Es difícil dividir el trabajo uniformemente
entre los P procesadores
No basta con asignar el mismo trabajo a
todos los procesadores porque el tamaño
de las tareas puede variar dependiendo
de los datos que use.
Ejemplo: guía telefónica
Cómputo - Comunicación
Balance de Carga
Los procesos que terminan antes
deben esperar al proceso que más
se demora
Tiempo ocioso
Menor utilización
Balance de Carga Estática
El programador decide a priori la cantidad
de trabajo que se le asigna a cada
proceso
Funciona bien en sistemas homogéneos
Todos los procesadores tienen las mismas
características
Cada proceso tiene la misma cantidad de
trabajo
No funciona bien en sistemas
heterogéneos
Balance de Carga Dinámica
Cuando un proceso finaliza su tarea,
saca más trabajo del proceso más
cargado
Ideal para sistemas heterogéneos
con carga de trabajo no uniforme
No funciona bien
en sistemas
distribuidos
Terminología
Escalabilidad: Habilidad de demostrar
un incremento en el speed-up
paralelo
Término impreciso: se puede usar
para describir el hardware o el
software.
Escalabilidad
Hardware
Al incrementar el número máquinas
mejora la performance del sistema
Escalabilidad con tamaño de problema fijo
Analizar cómo varía el tiempo paralelo y la eficiencia al aumentar P
¿Cuántos P necesito para obtener una eficiencia del 50%?
Escalabilidad
Software
Al aumentar el tamaño del
problema no decrece la
performance del sistema
Tamaño del problema: Tamaño del
input o número de pasos en el
mejor algoritmo secuencial
Terminología
Latencia: tiempo que toma en transmitir
un mensaje de un lugar a otro. (Demora)
Bandwidth: cantidad de bits que pueden
ser transferidos por segundo. Costo alto
en sistemas heterogéneos.
Costo de comunicación =
Latencia + Bandwith
Terminología
Portabilidad
Características de ciertos programas
que les permite ser utilizados en
distintas arquitecturas sin que precise
Modificaciones de importancia
Clasificación de las
Computadoras Paralelas
Aspectos del Hardware
Clasificación de Flynn (1972)
SISD: único flujo de instrucciones
aplicado a un único flujo de datos
SIMD: único flujo de instrucciones
aplicado a múltiples flujos de datos
MIMD: múltiplo flujo de instrucciones
aplicado a múltiple flujo de datos
SISD
Todas las computadoras con un único
procesador, desde computadoras personales
hasta supercomputadoras
PC, Workstations
Programa
IS
CU
Procesador
Datos
DS
PU
MM
SIMD
PU1
DS1
DS2
PU2
CU
PUN
IS
load Ai
Load Bi
Ci = Ai*Ci
MM2
IS
DSN
Ejemplo:
MM1
SINCRONISMO
MMN
MIMD
IS1
CU
IS2
CU
CU
ISN
PU1
DS1
DS2
PU2
DSN
PUN
ISN
ASINCRONO
MM1
MM2
MMN
IS1
MIMD
MIMD
C. Distribuidas
y Paralelas
Memoria
Distribuida (privada)
Memoria
Compartida
Multiprocesador
BUS
Switch
Multicomputador
BUS
Switch
Paradigmas de computación Paralelas
Memoria Compartida
Memoria Distribuida
Mecanismos de locks y
Sincronización.
Responsabilidad del
programador
Mecanismos de
comunicación
Todos los procesadores
ven los mismos datos
Cada procesador ve
datos diferentes
Distribución de datos
M. Compartida vs. M. Distribuida
M.Compartida
Se puede compartir datos rápidamente entre las
tareas
Acceso a datos en forma amigable para el
programador
Escalabilidad pobre entre CPUs y memoria.
Son caras
M.Distribuida
Escalable
No
existe problemas de coherencia de memoria.
Costo bajo.
Puede ser difícil mapear estructuras de datos en
diferentes procesadores (SAT-tree).
MIMD- Hardware
Topologías de M. Compartida
Arquitectura basada en BUS
Existe saturación del bus
Coherencia de cache
Performace limitada al bandwidth del bus
Arquitecturas basadas en Switch
Puede ser visualizada como una grilla de
cables con SW en las intersecciones y memoria
y procesadores en las terminales.
Muy cara
MIMD- Hardware
Topologías de M. Distribuida
Redes basadas en BUS
Muy sencillas
No escalables
Redes basadas en SW
Rápidas
Jerarquía de SW: Fat-tree
Fat-Tree
Como programar en M. Compartida?
Los procesadores 1.. N
requieren la variable x
Sólo hay un lugar donde
buscar
Condiciones de competencia:
Usar Sync. Para evitar conflictos
Como programar en M. Compartida?
Un único proceso puede crear
múltiples threads concurrentes
Cada thread encapsula su propia ruta de ejecución
Cada thread tiene estados locales y recursos compartidos
Los threads se comunican a través de recursos compartidos como
la memoria
Como programar en M. Distribuida?
Los procesadores 1.. N requieren la
variable x
Hay n lugares donde buscar
Cada procesador tiene su
propia X
El valor de X puede variar
Para que el P1 busque X en P2:
P1 envía una petición de X a P2
P2 envía una copia de X a P1
P1 recibe la copia
P1 la almacena en su memoria
Pasaje de Mensajes
Y
Creación de Procesos
Creación de procesos
Estática:
Todos los procesos se especifican antes
de la ejecución
El sistema ejecutará un número fijo de
procesos
El programador lo determina por línea
de comando
SPMD y MPMD(Master-Slave)
Creación de procesos
Dinámica:
Un proceso puede ser creado e inicializado
durante la ejecución de otro proceso
También pueden ser destruidos
La creación y destrucción puede realizarse en
forma condicional (varía el número de procesos)
MPMD
tiempo
spawn()
Proceso 1
Proceso 2
Pasaje de mensajes
Las arquitecturas con memoria distribuida
usan comunicación explícita para
intercambiar datos
El intercambio de datos requiere sincronización
(cooperación) entre los senders-receivers
Cómo se describen los datos?
Cómo se identifican los procesos?
Qué significa que se complete un envío o recepción?
Ejemplo
Se quiere calcular la distancia entre cada punto de
A[1..4] y B[1..4] y guardar los resultados en
C[1..4][1..4]
Ejemplo
Se quiere calcular la distancia entre cada punto de
A[1..4] y B[1..4] y guardar los resultados en
C[1..4][1..4]
Podemos dividir el
Trabajo entre dos
procesadores
P1 envía datos a P2
P1 y P2 computan
P2 envía datos a P1
Ejemplo
Patrones de comunicación
Al usar pasaje de mensajes los programas
deben entender el cómputo y organizar la
comunicación correctamente
Punto a Punto
Broadcast (1 a todos) Reduce (todos a 1)
All to all
Scatter (1 a varios) Gather (varios a 1)
Point-to-Point
Método básico de comunicación entre 2
procesos
El procesador origen envía un mensaje al
procesador destino
El procesador destino recibe el mensaje y lo
procesa
El mensaje generalmente incluye
Datos
Longitud del mensaje
Dirección destino y posiblemente un tag
Synchronous vs. Asynchronous
Synchronous
No utiliza buffers
El receptor notifica cuando
recibe el mensaje
El proceso que envía espera
a que el destino reciba todo el
mensaje
tiempo
tiempo
send()
Solicita envío
Acknowledgement
send()
Mensaje
recv()
recv()
Synchronous vs. Asynchronous
Asynchronous
No existe confirmación
Un usa buffers
Blocking vs. Non-Blocking
Blocking = Sync && Non-Blocking = Async
MPI son diferentes
tiempo
send()
recv()
Blocking vs. Non-Blocking
No Bloqueante
Permite ejecutar la próxima instrucción sin importar
que la rutina send() haya sido localmente completada
Es responsabilidad del programador que los datos que
se envían no sean modificados en las próximas
instrucciones
Fuente de Deadlock - Bloqueante
Si no hay suficiente capacidad en el buffer,
las operaciones send esperan hasta que
haya suficiente espacio disponible
Qué sucede con este código:
Depende del
tamaño del
buffer
Soluciones
Incrementar el tamaño del buffer
Ordenar las operaciones send y recv en
forma más cuidadosa
Broadcast
Un
proceso envía la misma
información a otros
procesadores
Se identifican los procesos que van a participar
en el broadcast
Mediante un nombre de grupo que es usado
como parámetro por la función de broadcast
El proceso que hace broadcast también puede
recibir el mensaje
Incluye send+sync
Broadcast
Si queremos paralelizar:
Scatter
Envía un conjunto de elementos de un
arreglo desde el procesador origen a un
conjunto de procesos
Process 0
Process 1
dato
dato
Process N
dato
Acción
buf
Código
scatter
scatter
scatter
Gather
Un procesador recolecta los valores de
otros procesadores
Se utiliza luego de realizar cómputos en
forma paralela
Process 0
Process 1
dato
dato
Process N
dato
Acción
buf
Código
scatter
scatter
scatter
Gather - Ejemplo
Processor 0..N
{
…
int r = rand();
int k = 0;
int buff[N];
Gatther( 0, &buff, r, pid );
for (i=0;i<N;i++)
k+=buff[i];
…
}
P0
P1
P2 P3 P4
4
7
8
19
30
11
K= 433
27
8
3
P5
3
r
Reduction
Cada procesador comienza con un valor y
necesita conocer la suma de los valores
almacenados en otros procesadores
Un “reduction” combina datos de todos los
procesadores y los retorna a través de una
operación
Algunas operaciones que se pueden aplicar son:
ADD, OR, AND, MAX, MIN, etc.
Ningún procesador puede finalizar un “reduction”
antes que los otros procesadores hayan
contribuido con sus valores
Ejemplo
Ejemplo en Paralelo
Paralelismo de datos
Paralelismo de tareas
y
Diseño de software paralelo
Paralelismo de Datos
Se caracteriza por la ejecución paralela de
las mismas operaciones sobre diferentes
partes de un conjunto de datos
suficientemente grande
Tipos de paralelismo de datos:
SPMD y MPMD
Paralelismo de Datos
Es simple de programar
Existe una única estructura de control o
ejecución
El paralelismo aparece via pasos de
paralelismo de datos
Forma de particionar los datos
Paralelismo de Datos
for all i: A[i]=2*A[i]
P0
4
2
P1
8
7
1
P2
0
4
5
3
4
8
1
Paralelismo de datos
8
4
16 14 2
0
8
10 6
8
16 2
for all i>0: A[i]=A[i]+A[i-1]
8
12 20 30 16 2
8
Suma = 0….
18 16 14 24 18
Paralelismo de datos
secuencial
Paralelismo de Tareas o funcional
Ejecuta diferentes operaciones sobre
los mismos o diferentes datos
Se enfoca en la división
de tareas
Paralelismo de Tareas
v = alpha();
w = beta();
x = gamma(v, w);
y = delta();
printf ("%6.2f\n", epsilon(x,y));
alpha
Se puede ejecutar
alpha, beta, Y gamma, delta
en paralelo.
beta
gamma
delta
INDEPENDENCIA DE DATOS
epsilon
Ejemplo 2
Procesamiento de Señales: Un conjunto signal-data de
audio se transmite a través de tres filtros computacionales
distintos.
Cada filtro es un proceso independiente. El primer
segmento de datos debe pasar por el primer filtro antes
de pasar al segundo.
Cuando lo hace, el segundo segmento de datos pasa por
el primer filtro.
En el momento en el tercer segmento de datos se
encuentra en el primer filtro, las tres tareas están
ocupadas.
Divide y Vencerás
Es un método elegante para resolver problemas
Se divide el problema en problemas más pequeños,
luego se resuelven las partes en forma separada y
se combinan los resultados parciales para obtener
el resultado final
Se utiliza recursivamente para dividir el problema
hasta alcanzar un punto en el que el problema es
trivial
X0 …. Xn/m-1 xn/m…. X2n/m-1
….
suma
x(m-1)n/m-1….. Xn-1
Divide y Vencerás
MASTER
s = n/m;
//cantidad de elementos para los slaves
for ( i=0, x=0; i<m; i++, x = x+s )
send( &numbers[x], s, Pi );
//envía s números al slave Pi
result = 0;
for( i=0;i<m; i++ )
recv( &part_sum, Pany);
sum += part_sum;
//Espera resultados de los slaves
//Acumula suma parciales
SLAVE
recv( numbers, s, Pmaster );
part_sum = numbers[0];
for( i=0; i< s; i++ )
part_sum += numbers[i];
send( &part_sum, Pmaster );
//Recibe s números del master
//Realiza la suma
//Envía resultados
Con broadcast?
Divide y Vencerás: Análisis
El algoritmo secuencial requiere n sumas, con
una complejidad de O(n).
El algoritmo paralelo utiliza m+1 procesos.
Dividimos el análisis en etapa de cómputo y
comunicación
Etapa 1: Comunicación:
m slaves leen n/m números con un costo de
tcomm1=m*(tstartup+(n/m)tdata)
Etapa 2: Cómputo:
Los procesos esclavos suman n/m números
requiriendo n/m sumas.
tcomp1 = n/m
Divide y Vencerás: Análisis
Etapa 3: Comunicación:
Se envían los resultados parciales de las sumas
tcomm2 = m(tstartup+tdata)
Etapa 4: Cómputo:
Suma final de m sumas parciales
tcomp2 = m;
Costo total
tp = tcomm1 + tcomm2 + tcomp1 + tcomp2
= m(tstartup+(n/m)tdata)+m(tstartup+tdata) + n/m + m
= 2mtstartup+(n+m) tdata + n/m + m
Divide y Vencerás: Recursivo
Esta formulación crea un árbol binario de
procesos
Al inicio, el problema raíz del árbol toma un
problema y lo divide en dos partes más chicas
La división del problema continúa hasta que las
hojas del árbol han recibido los problemas más
básicos
Cada hoja retorna la solución de su problema al
nodo padre
Cada proceso padre combina y/o aplica alguna
operación a la solución entregada por los nodos
hijos
Eventualmente la raíz genera la solución al
problema original
Divide y Vencerás: Recursivo
add( int *s)
{
if( numbers(s)<= 2 ) return (s[0] + s[1]);
else
{
Divide (s, s1, s2 ); //Divide s en dos grupos
part_sum1 = add(s1);
part_sum2 = add(s2);
return( part_sum1 + part_sum2);
}
Problema inicial
}
Divide el problema
Tareas finales
Divide y Vencerás: Implementación
Paralela
En una implementación secuencial
se visita un nodo del árbol por vez
Una implementación paralela
permite visitar varios nodos
simultáneamente
Si se asigna un proceso a cada nodo
P0
Cada proceso solo
P1
estará activo
en un nivel del árbol
P3
2m sub-tareas
2m+1-1 procesos
P2
P4
P5
P6
Divide y Vencerás: Implementación
Paralela
una solución mas eficiente es re-usar los procesos existentes
P0
P0
P4
P0
P0
P2
P1
P2
P4
P3
P4
P6
P5
P6
P7
También se puede aplicar a tareas que son divididas en más de dos
partes
Bucket sort: Secuencial
La mayoría de los algoritmos de ordenación
secuencial se basan en las operaciones de
“comparar” e “intercambiar”
Bucket sort:
Es un algoritmo de partición
Funciona bien si los números se distribuyen
uniformemente en un intervalo [0..a-1]
El intervalo se divide en m regiones denominadas
buckets
Para ubicar un número en un bucket, i/m y usar el
resultados para identificar el bucket
--------------------------------------------
buckets
sort
merge
Bucket sort: Secuencial
Algoritmo secuencial:
Se divide el número i por el número de buckets y me
da el identificador del bucket donde lo debería ubicar.
Es decir los números se distribuyen uniformemente en
buckets. Si los números están uniformemente
distribuidos, en cada bucket hay n/m números.
Eso permite balancear la carga de trabajo asignada a
cada bucket.
luego se ordenan en forma secuencial los números de
cada buckets y finalmente se aplica una función de
merge
--------------------------------------------
buckets
sort
merge
Bucket sort: Paralelo
Alternativa 1: Asignar un bucket a cada
procesador (todos los procesadores mantienen
el arreglo de números desordenados)
Números desordenados
--------------------------------------------
Buckets
grandes
sort
merge
Bucket sort: Paralelo
Alternativa 2:
Se divide la secuencia en m regiones, una para cada procesador.
Cada procesador genera buckets más pequeños y distribuye los
números en esos buckets.
Estos buckets pequeños se vacían en P buckets mas grandes para
ser ordenados.
Para ello c/procesador envía un bucket chico a c/u de los otros
procesadores (bucket i al procesador i)
Números desordenados
-------------------------------------------procesadores
Buckets mas pequeños
Buckets
grandes
sort
merge
D&V Paralelo
Tipos de Algoritmos (Input-Output)
Los problemas se pueden clasificar según sus
datos de entrada y salida
Común-Común (CC): las variables paralelas de
entrada y salida son comunes (replicadas) a todos
los procesadores del grupo
Común-Privado (CP): las variables paralelas de
entrada son comunes (replicadas) pero las
variables resultado quedan privadas en cada
procesador
Privada-Común (PC): las variables paralelas de
entrada son privadas de cada procesador y las
variables resultado son replicadas
Privada-Privada (PP): las variables de entrada y
salida son privadas
Caso de estudio:
Algoritmo shortest path
Un grafo G(V,E), donde V es el conjunto
de vértices y E es el conjunto de arcos
conectando vértices en V.
En un grafo dirigido cada arco tiene una
dirección
Un grafo puede ser representado como
una matriz de adyacencia
Aij = 0 si no hay un arco que une i con j
Aij = 1 si hay un arco que une i con j
Caso de estudio:
Algoritmo shortest path
Es un problema importante en la teoría de grafos
y tiene gran aplicación en problemas de
comunicación y otros problemas computacionales
El problema involucra encontrar el paso más corto
entre todos los pares de vértices
0
3
1
2
0
1
2
3
0 1 2 3
0 1 0 0
0 0 1 1
0 0 0 0
1 0 1 0
Matriz de Adyacencia:
dice si hay un arco que une 2 vértices
Algoritmo shortest path
La idea es determinar si el paso
desde el vértice vi al vértice vj vía
vk, es más corto que el menor paso
conocido
vk
vi
vj
Algoritmo shortest path
El paso desde el vértice vi la vértice vj es la
secuencia de arcos que los une y ningún arco se
repite 2 veces.
El problema requiere que encontremos el camino
mas corto
El algoritmo toma como entrada una matriz de
adyacencia A (NxN) y computa una matriz S(NxN)
Sij tendrá la longitud del paso más corto entre vi y
vj, o -1
Algoritmo shortest path
El algoritmo obtiene la matriz S en N pasos,
construyendo en cada paso k una matriz
intermedia I(k) que contiene el paso más corto
conocido entre cada par de vértices.
Inicialmente I(0) contiene la longitud entre (vi,vj),
si existe un arco, de lo contrario será 0.
Durante el k-ésimo paso se evalúa nuevamente Iij
para determinar si:
El mejor paso conocido entre vi, vj es más largo que
las longitudes combinadas desde vi a vk y desde vk
a vj. De ser así se actualiza Iij
Algoritmo shortest path
Algoritmo shortest path: Paralelo
Repartir las filas en P procesadores
en forma consecutiva
J=0;
for (i=0;i<P;i++)
{
for (;j< (N/P); j++)
send(i, fila j);
if(i==(P-1))
send(i, fila j+1)
}
Asigna un bloque contiguo a
cada procesador
Г
Cada tarea es root de al menos un broadcast
Los datos requeridos en el késimo paso no le pertenecen
al procesador
Computación
Pipelined
Pipelined
T0
T1
T2
T3
El problema se divide en tareas que se
completan una después de otra.
En la programación paralela cada tarea se
ejecuta en un procesador diferente
Cada etapa contribuye a resolver el
problema y pasa información necesaria
para la siguiente etapa
Pipelined
Es posible incrementar la velocidad
de ejecución:
1.
2.
3.
Si se ejecuta mas de una instancia del
problema
Si una serie de datos se procesan con
múltiples operaciones
Si los datos pueden ser enviados a las
siguientes etapas antes que la etapa
actual finalice
Pipelined
Si se ejecuta mas de una instancia
del problema
procesos
1.
P4
Inst.1 Inst.2
P3
Inst.1 Inst.2 Inst.3
P2
Inst.1 Inst.2 Inst.3 Inst.4
P1 Inst.1 Inst.2 Inst.3 Inst.4 Inst.5
tiempo
Se utiliza para ejecutar simulaciones con diferentes parametros para
obtener resultados comparativos.
Pipelined
1.
Si una serie de datos se procesan
con múltiples operaciones
Elementos de vector
2.
d4
P0
P1
P0
P1
P2
P1
P2
P3
P1
P2
tiempo
P3
P4
d3
d2
d1
P0
P0
Cada proceso realiza una operación diferente sobre los elementos
Se utiliza para cálculos aritméticos, como multiplicar elementos de vectores
1.
2.
3.
Pipelined
Si los datos pueden ser enviados a
las siguientes etapas antes que la
etapa actual finalice
P4
Se transfiere
suficiente inf.
para comenzar
la siguiente etapa
P4
P3
P3
P2
P2
P1
P1
P0
P0
tiempo
tiempo
Ejemplo
Problema: Sumar una lista de
números almacenados en diferentes
procesadores
∑
P1
∑
∑
P2
P3
∑
P4
recv( Pi-1, acumulation );
accumulation += number;
send( Pi+1, accumulation)
P5
Tipos de Paralelismos
Threads
La estructura más común para
especificar procesos concurrentes es
FORK-JOIN
Programa principal
FORK
FORK
FORK
JOIN
JOIN
JOIN
Sistema de memoria compartida.
Threads
IP
Son rutinas livianas que comparten la misma zona
de memoria y las variables globales
code
Heap
IP
code
Heap
stack
threads
Rutinas de
Interrupción
stack
IP
Files
Files
stack
Proceso
Rutinas de
Interrupción
Threads
La creación de threads es 3 ordenes
de magnitud menor a la creación de
un proceso
La sync de los threads se puede
realizar más eficientemente que la
sincronización de procesos
Threads: Ejemplo
Threads: memoria compartida
Instrucción
x = x+1;
Proceso 1
read x
compute x+1
write x
tiempo
Proceso 2
read x
compute x+1
write x
Variable x
write
write
read
read
+1
+1
Proceso 1
Proceso 2
Secciones Críticas
- Locks
El problema de variable compartida puede ser generalizada a cualquier recurso.
Por ej. I/O dispositivos
Locks
Locks: son variables de 1 bit que se
coloca en 1 para indicar que el proceso
ha ingresado a la sección critica. Y se
coloca en 0 para indicar que no hay
procesos en la sección critica.
Estos mecanismos generalmente se
implementan por hardware.
Pthread
El programa principal es un thread.
Un thread separado puede ser creado y destruido
utilizando:
pthread_t thread1;
pthread_create( &thread1, NULL, (void*)proc1, (void*) &arg);
pthread_join( thread1, void *status);
thread1
Main program
pthread_create( &thread1, NULL, (void*)proc1, (void*) &arg);
pthread_join( thread1, void *status);
proc1(&arg)
{
….
return(*status);
}
Pthread
#include <pthread.h>
pthread_cancel(&thread1)
for (j=0;j<NUM_THREADS;j++)
Detached
thread: threads que se crean y se terminan sin la necesidad de
usarifun(threads[j]
join se llaman!=
thread
tid)detached
pthread_cancel(threads[j]);
pthread_self
pthread_mutex_t mutex1;
void
print_it(void *arg)
pthread_mutex_init(&mutex1,NULL);
{
pthread_mutex_destroy(&mutex1);
pthread_t tid; /* get the calling thread's ID */
tid = pthread_self();
pthread_mutex_lock(
mutex1 );
printf("Thread %d \n", tid);
pthread_mutex_unlock( mutex1 );
}
Pthread
Destroying Mutexes
struct obj
thread_mutex_t
foo_mutex;
{
void foo()
pthread_mutex_t om;
{
int refcnt; ...
pthread_mutex_init(&foo_mutex,NULL);
};
obj_done(struct obj *op)
pthread_mutex_lock(&foo_mutex);
/* Do{work. */
pthread_mutex_lock(&op->om);
x = x+1;
if (--op->refcnt == 0)
pthread_mutex_unlock(&foo_mutex);
{
}
pthread_mutex_unlock(&op->om);
pthread_mutex_destroy(&op->om);
free(op);
}
else
pthread_mutex_unlock(&op->om);
}
Hardware?
Todas las computadoras modernas
tienen cache
Hyperthreading. Cada núcleo
dispone ahora de dos hilos de
procesamiento, con lo que el
sistema ve el microprocesador
como si tuviera ocho núcleos en
vez de cuatro
L2: 8Mb
Hardware
• Si un therad en un core requiere un dato se trasfiere
desde la memoria hasta la cache del core (se hace una
copia).
• Posteriormente cuando el thread quiere obtener el
dato accede a su cache.
• Si otro thread ubicado en otro core quiere el mismo
dato, se hace una nueva copia del dato en la cache del
nuevo core que lo requiere. (hay 2 copias).
• El problema surge cuando un thread modifica el
contenido del dato. Luego se debe usar un protocolo
de coherencia para asegurar la correctitud de los
datos.
Hardware
Protocolo de coherencia de cache
Política de actualización: se actualiza todas
las copias del dato en todas las cachés
Política de invalidar (más común): cuando
se modifica una copia en una caché, las
otras copias son invalidadas utilizando un bit
de validación.
Hardware
La caché se organiza en bloques de
direcciones continuas
caché
Code:
a+=2;
b+=2;
c+=a+b;
bloques
ab
c
RAM
False sharing: un bloque puede ser pedido por varios threads, pero
cada thread accede a datos diferentes. Cuando se actualiza un dato
partes de las copias del bloque en otros cores deben ser actualizados
o invalidados
False-sharing
RAM
bloque
Address
tag
7
6
5
4
3
2
1
0
cache
cache
Core 1
Bloque en cache
Core 2
Ejemplo
sum
int sum, a[1000];
sum = 0;
for( i=0;i<1000; i++)
sum += a[i];
a
------------
Solución 1
Proceso 1
sum1 = 0;
for( i=0; i<1000; i+=2 )
sum1 += a[i];
sum += sum1
Proceso 2
sum2 = 0;
for( i=1; i<1000; i+=2 )
sum2 += a[i];
sum += sum2
Ejemplo
sum
N procesos tomando
números de a[]
a
------------
global_index
int a[array_size];
int global_index;
int sum = 0;
pthread_mutex_t mutex1;
Int nth = 10;
main()
{
int i;
pthread_t thread[nth];
for( i=0; i<array_size; i++ )
a[i] = i+1;
for(i=0;i< nth; i++ )
pthread_create(&thread[i],NULL,
slave, NULL);
for(i=0; i<nth; i++ )
pthread_join(thread[i],NULL);
}
Void *slave( void *ignorado)
{
int local_index, partial_sum = 0;
do {
pthread_mutex_lock(&mutex1);
local_index = global_index;
global_index++;
pthread_mutex_unlock(&mutex1);
if (local_index < array_size)
partial_sum += a[local_index];
}while(local_index < array_size )
pthread_mutex_lock(&mutex1);
sum += partial_sum;
pthread_mutex_unlock(&mutex1);
}
OpenMP
#include <omp.h>
g++-4.2 main.cc -o main.out –fopenmp
Las directivas se especifican con #pragma
#pragma omp directive-name[clause[,] clause]...
Al final de una región paralela hay una
sincronización implícita. Solo el thread master
continúa la ejecución.
Cuando un thread encuentra un constructor
paralelo, un grupo de threads es creado
OpenMP: clausuras
Private (lista de variables) En esta la lista de variables puede ser
separada por ",“ y para cada una de ellas se genera una copia en
cada thread, esta copia no tiene relación con la original y no es
inicializada a menos que se utilice firstprivate.
Shared (lista de variables) En esta las variables de la lista son
comunes a todos los threads y cada uno de ellos puede modificarla
afectándola en forma global.
Threadprivate (lista de variables) Hace que la lista sea privada a
cada thread pero globales dentro de un thread.
Reduction (operador:lista de variables) Realiza una operación de
reducción sobre las variables que aparecen en la lista utilizando el
operador/intrínseco especificado. El operador puede ser: +, *, -,
&(and), |(or), ^(eqv), &&(neqv). El intrínseco puede ser: || (max),
(min), (and), (or).
if(expresión escalar): los threads se crean si al evaluar la expresión
es verdadera.
OpenMP
int omp_get_threads_num(void) Devuelve el
identificador del thread.
int omp_get_num_threads(void) Devuelve cuántos
threads se están utilizando
int omp_get_num_procs(void) Devuelve el número
de procesadores accesibles
void omp_set_num_threads(int) Indica el número
de threads a utilizar
int omp_get_max_threads(void) Devuelve el
máximo posible de threads
OpenMP: Variables de entorno
OMP_NUM_THREADS Indica el
número de threads a usar.
export OMP_NUM_THREADS=4
setenv OMP_NUM_THREADS 4
set OMP_NUM_THREADS=4
OpenMP: Ejemplo
Si no quieren usar variables de
entorno pueden tener el mismo
efecto usando
omp_set_num_threads(NT);
OpenMP: Tipos de constructores
DO / for – Comparten las
iteraciones de un loop.
Representa el “paralelismo
de datos"
SECTIONS – Divide el trabajo
en secciones discretas. Cada
sección se ejecuta por un thread.
Paralelismo de tareas
Ejemplo
#pragma omp for[clause[,] clause]...
{
ciclo for
}
FOR
SCHEDULE(type, chunck): Describe cómo se dividen las iteraciones
de un loop entre los threads.
STATIC: Las iteraciones se dividen en chunks y asignados
estáticamente a los threads
DYNAMIC: Las iteraciones se dividen en chunks y asignados
dinámicamente a los threads. Cuando un thread termina un chunk
se le asigna otro
Ejemplo static
#include <opm.h>
#define SIZE 4
#define N 8
int main( )
{
int i,chunk;
float a[N], b[N], c[N];
for( i=0;i<N ;i++)
a[i] = b[i] = i*1.0;
chunck = SIZE;
#pragma opm parallel shared(a,b,c) private(i)
{
#pragma opm schedule( static, chunk )
for( i=0;i<N;i++)
c[i] = a[i]+ b[i];
}
}
Ejemplo
SECTIONS
SECTIONS / END SECTIONS
Debe incluirse en una región paralela.
Las secciones se dividen entre los “threads”.
Cada “thread” ejecuta una sección diferente.
Es posible realizar paralelismo a nivel de tarea.
SECTION define cada una de las secciones.
OpenMP
SECTION
OpenMP: Directivas
#pragma omp single: sólo un thread
ejecuta el código
#pragma opm parallel shared(a,b,c) private(i)
{
BLOCK1
#pragma opm single
{
BLOCK2
}
BLOCK3
}
OpenMP: Directivas
#pragma omp master: el código a
continuación lo ejecuta solo el
thread master
#pragma opm parallel shared(a,b,c)
private(i)
{
BLOCK1
#pragma opm master
{
BLOCK2
}
BLOCK3
}
OpenMP: Directivas
#pragma omp barrier: barrera de
sync.
#pragma opm parallel shared(a,b,c)
private(i)
{
BLOCK1
#pragma opm barrier
BLOCK3
}
OpenMP: Directivas
#pragma omp critical: regiones
críticas
#pragma opm parallel shared(a,b,c)
private(i)
{
BLOCK1
#pragma opm critical (zona1)
{
x = x+1;
}
BLOCK2
}
Descargar