Upload
gabby
View
50
Download
0
Embed Size (px)
DESCRIPTION
proParCurso 14/15. 4. 4. 2, 3, 2. 2, 2. 5. 4. Computadores Paralelos Programación basada en paso de mensajes Técnicas básicas de programación paralela Compulsiva, Divide y Vencerás, Pipeline, Síncrona, Equilibrado de carga y Terminación Programación basada en memoria común - PowerPoint PPT Presentation
Citation preview
proPar Curso 15/16
1 Computadores Paralelos
2 Programación basada en paso de mensajes
3 Técnicas básicas de programación paralela
Compulsiva, Divide y Vencerás, Pipeline,
Síncrona, Equilibrado de carga y Terminación
4 Programación basada en memoria común
5 Algoritmos y aplicaciones
Ordenación, …
4
4
2, 3, 2
2, 2
5
4
Procesamiento Paralelo Temario pasoMsj-2
2 PROGRAMACIÓN BASADA EN PASO DE MENSAJES
1 Recordar concurrencia pthreads: contar y descifrar
2 Un modelo de paso de mensajes• Opciones de programación• Creación de procesos• Rutinas genéricas de paso de mensajes
3 MPI• Introducción• Procesos• Envío y recepción de mensajes• Comunicación colectiva
4 Evaluación de programas paralelos
5 Herramientas de depuración y monitorización
proPar Recordar concurrencia pthreads pasoMsj-3
• contarPar.c: Número de apariciones de un número en un vector
6 2 0 7 4 9 3 4 9 8 0 6 7 9 6 0 6 7 9 8 6 2 5 2 6 4 7 9 3 5 2 1 7 3 2 6 6 4 4 0
const N = 40; objetivo = 6; numCPUs = 4;var vector array[1..N] of integer;
¿ Algoritmo paralelo ?
T1 T2 T3 T4
1 3 2 2
+8
proPar Recordar concurrencia pthreads pasoMsj-4int longRodaja, numVecesLocal[MAX_ESCLAVOS], *vector;
void *esclavo (void *parametro) { ..... }
int main (int argc, char *argv[]) { int i, numVeces, cardinalidad = atoi (argv[1]); int numEsclavos = atoi (argv[2]); pthread_t pids[MAX_ESCLAVOS];
// Pedir memoria e inicializar vector
// Crear esclavos y esperar a que terminen su trabajo for (i = 0; i < numEsclavos; i++) pthread_create (&pids[i], NULL, esclavo, (void *) i); for (i = 0; i < numEsclavos; i++) pthread_join (pids[i], NULL);
// Sumar los valores de todos e informar del resultado numVeces = numVecesLocal[0]; for (i = 1; i < numEsclavos; i++) numVeces = numVeces + numVecesLocal[i]; printf (“Veces que aparece = %d\n”, numVeces);}
%cuentaPar 1000000 4
proPar Recordar concurrencia pthreads pasoMsj-5
// Variables globalesint longRodaja, numVecesLocal[MAX_ESCLAVOS], *vector;
void *esclavo (void *parametro) { int yo, inicio, fin, i, j, numVeces;
yo = (int) parametro; inicio = yo * longRodaja; fin = inicio + longRodaja;
// Buscar en mi parte del vector numVeces = 0; for (i = inicio, i < fin; i++) if (vector[i] == NUM_BUSCADO) numVeces++; numVecesLocal[yo] = numVeces; pthread_exit (NULL);}
proPar Recordar concurrencia pthreads pasoMsj-6
5 1,286 4,26 0,85
6 1,127 4,86 0,81
7 1,113 4,92 0,70
8 0,998 5,49 0,69
Esclavos Tiempo Aceleración Eficiencia
1 5,480
2 2,721 2,01 1,01
4 1,408 3,89 0,97
cuentaPar 400.000.000 1..8 // Recorriéndolo diez veces
2 Xeon E5520 Quad2,26GHz • 8ML3 • 12GB • 500GB
proPar Recordar concurrencia pthreads pasoMsj-7
• descifra.c: Descifrar una clave basada en “crypt”
char *crypt(const char *key, const char *salt);
crypt (“abrir”, “aa”) => “aaHUVtmrCqHAw”
crypt (“ajaja”, “aa”) => “aaCV68P63epR6”
crypt (“clave”, “aa”) => “aa80JYxYfBfpI”
claveCruda claveCifrada
¿ aaSjbUR3erIrQ ? if (crypt (claveCruda, “aa”)
== claveCifrada) encontradaelse siguiente (claveCruda)
aaaaa .. zzzzz
¿ Paralelo ?
5 letras |a..z| = 26
proPar Recordar concurrencia pthreads pasoMsj-8
• descifraPar.c: Descifrar una clave basada en “crypt” 4 núcleos
aaaaa zzzzz
• ¿Qué claves a cada proceso?
0
1
2
3
aaaaa .. fzzzz
gaaaa .. lzzzz
maaaa .. szzzz
taaaa .. zzzzz
? ? ?
aaaaa, aaaae, ..
aaaab, aaaaf, ..
aaaac, aaaag, ..
aaaad, aaaah, ..
saltoRana
• ¿Cómo terminar?
encontradavarComún
proPar Recordar concurrencia pthreads pasoMsj-9#define MAX_ESCLAVOS 16#define FRECUENCIA_MUESTREO 1000
//------------- VARIABLES GLOBALES --------------------------------- int encontrada, numEsclavos; char cifradaBuscada [LONG_CLAVE_CIFRADA+1];
static void esclavo (int yo) { int i; int totalClaves, iMiPrimeraClave, clavesPorEsclavo; char clave [LONG_CLAVE_CRUDA+1]; char cifradaActual [LONG_CLAVE_CIFRADA+1];
// Inicializaciones totalClaves = numClavesPosibles(); clavesPorEsclavo = totalClaves / numEsclavos; iMiPrimeraClave = (yo-1) * clavesPorEsclavo; if (yo == (numEsclavos)) clavesPorEsclavo = totalClaves - iMiPrimeraClave;
// Busqueda en mi trozo del espacio de claves claveCrudaIesima (iMiPrimeraClave, clave); for (i=0; i<clavesPorEsclavo; i++) { if (((i%FRECUENCIA_MUESTREO) == 0) && encontrada) break; cifrar (clave, cifradaActual); if (strcmp (cifradaActual, cifradaBuscada) == 0) { encontrada = TRUE; printf ("%s ", clave); break; } siguienteClaveCruda (clave); }}
proPar Recordar concurrencia pthreads pasoMsj-10
int main(int argc, char *argv[]) { int numClaves, i; struct timeval t0, tf, t; pthread_t pids[MAX_ESCLAVOS];
numEsclavos = atoi(argv[2]); numClaves = abrir (argv[1]);
// Inicializacion if (leerClaveCifrada (cifradaBuscada) != 0) { printf ("La clave no es correcta \n"); return 0; } gettimeofday (&t0, NULL);
encontrada = FALSE; // Crear esclavos y esperar a que terminen su trabajo for (i=1; i<=numEsclavos; i++) pthread_create (&pids[i], NULL, esclavo, (void *) i); for (i=1; i<=numEsclavos; i++) pthread_join (pids[i], NULL); gettimeofday (&tf, NULL);
timersub (&tf, &t0, &t); printf ("Tiempo => %ld:%ld seg:mseg\n", t.tv_sec, t.tv_usec/1000); return 0;}
¡¡ No la encuentran !!
No reentrante
crypt()
crypt_r()
proPar Recordar concurrencia pthreads pasoMsj-11
2 Threads0:000
11:114
13:654
23:208
0:016
5:635
11:761
11:991
14:594
23:487
115:460
4 Threads0:000
10:905
1:991
11:735
0:015
5:042
11:799
0:109
2:912
11:857
56:365
clavesaaaaa
galas
hojas
musas
nadas
pumas
tizas
tomos
vasos
zzzzz
Total
secuencial0:000
10:819
13:571
23:065
23:420
28:406
34:818
35:196
37:842
46:796
253:933
PC9: 2 Xeon E5520 Quad 2,26GHz
proPar Opciones de programación pasoMsj-12Entornos de programación paralela en los 90 “Tim Mattson - Intel”
proPar Opciones de programación pasoMsj-13
1 A Pattern Language for Parallel Programming
2 Background and Jargon of Parallel Computing
3 The Finding Concurrency Design Space
4 The Algorithm Structure Design Space
5 The Supporting Structures Design Space
6 The Implementation Mechanisms Design Space
7 A Brief Introduction to OpenMP
8 A Brief Introduction to MPI
9 A Brief Introduction to Concurrent Programming in Java
2005
proPar Opciones de programación pasoMsj-14
1. Diseño específico de un lenguaje: Occam Transputer
2. Extensión de lenguaje existente: Fortran M, CC++, Cilk++
www.netlib.org/fortran-m
www-unix.mcs.anl.gov/dbpp/text/node51.html
www.cilk.com
3. Biblioteca de paso de mensajes sobre C, Fortran, C++
PVM: www.csm.ornl.gov/pvm
MPI: www-unix.mcs.anl.gov/mpi
HPC++: www.extreme.indiana.edu/hpc++/index.html
Paralelización automática: El compilador extraeparalelismo del código secuencial
¿ Sistema Operativo ?
OpenMP
1979 Proyecto Europeo: Inmos SGS-Thomson ICL ... †
Objetivo: µP de altas prestaciones, como elemento básico paraconstruir máquinas paralelas (multicomputadores)
1992: habían vendido 500.000 unidades (µP+1MB => 180.000pts)
Característica relevante: 4 enlaces de comunicación (canales)
T8000
1
2
3
Ejecución eficiente de n procesos que envían/reciben mensajes por canales
P1
P2
P3
proPar Opciones … (TRANSPUTER) pasoMsj-15
cP3 ! dato
cP2 ? dato
proPar Creación de procesos pasoMsj-16
• ¿Cómo podría ser contarPar.c si no hay memoria común?
1 3 2 2
6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 …
+8
esclavo1 esclavo2 esclavo3 esclavo4
maestro6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 …
• El vector lo tiene un proceso “maestro”
• El maestro: reparte “envía” trabajo a los “esclavos” y recoge “recibe” resultados
6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 …
13 2 2
2 tipos distintos de procesos
proPar Creación de procesos pasoMsj-17
• ¿Cómo podría ejecutarse la aplicación?
maestro
esclavo1 esclavo2 esclavoN
Un proceso x núcleo
M E E E
• Dos ejecutables: maestro.exe y esclavo.exe
maestro.c esclavo.c
maestro.exe esclavo.exe
Multiple Program Multiple Data
MPMD
maestro.exe esclavo.exe
• Creación de procesos: estática vs dinámica
¿Arquitecturas distintas?¿ SPMD ?
proPar Creación de procesos (creación dinámica) pasoMsj-18
• MPMD: Multiple Program Multiple Data
---------------------------spawn (“esclavo”, 4, ...)---------------------------
maestro.c
---------------------------contarEnTrozo (......)---------------------------
esclavo.c
maestro esclavo
%pvmpvm>add PC2 .....pvm>spawn maestro
M E E
proPar Creación de procesos (creación estática) pasoMsj-19
• SPMD: Single Program Multiple Data
programafuente
*.exe *.exe *.exe
M E
%mpirun –np 9 sort
%mpirun –p4pg fiConf sort
---------------------------if (miIdProceso == 0) maestro()else esclavo()---------------------------
sort.c
0 1 8
proPar Creación de procesos pasoMsj-20
• A veces, viene bien que el maestro también trabaje
esclavo1 esclavo2 esclavo3
maestro06 2 0 … 0 6 7 … 6 2 5 … 2 1 7 …
0 6 7 … 6 2 5 … 2 1 7 …
1
3 2 2
• Modelo SPMD y creación de procesos estática
proPar Rutinas genéricas de paso de mensajes pasoMsj-21
• Pi.enviar(Pj, &msj, ...) Pj.recibir(Pi, &msj, ...)
---------------------------enviar (esclavo, &rodaja[k], ...)---------------------------
sortM---------------------------recibir (maestro, &miRodaja, ...)---------------------------
sortE
• Máquina
• PID_Local
Varias semánticas:
• Bloqueante (Síncrona | Rendezvous)
• No bloqueante (Asíncrona: Capacidad de almacenar)
• Temporizada (Tiempo máximo de bloqueo)
enviar( Pi, &msj, temporización, )
0
t
proPar Rutinas genéricas de paso de mensajes pasoMsj-22
• Bloqueante vs NoBloqueante
--------------------enviar...--------------------
--------------------recibir...--------------------
El primero se bloquea
Transferencia sin buffers adicionales
Se sabe que se ha recibido
--------------------enviar...--------------------
--------------------recibir...--------------------
Buffer
Se desacopla env | rec
Gestión de buffers
¿ Dónde ?
¿Se ha recibido? => msjACK
enviar( Pi, &msj, temporización, ...)
proPar Rutinas genéricas de paso de mensajes pasoMsj-23
• recibirDeCualquiera (&msj) | recibir ( -1, &msj)
sortE1 sortEn
sortM---------------------------quien = recibir (-1, &rodaja[k], ...)---------------------------
sortM
• Mensajes etiquetados
PPPPPPPH
enviar (S, &msj, tipoP)
enviar (S, &msj, tipoH)
recibir (-1, &msj, tipoH)
recibir (-1, &msj, -1 )
Cliente Servidor
Cliente
Cliente
proPar Paso de mensajes entre “grupos” pasoMsj-24
• Broadcast (a todos) Multicast (a unos concretos)
---------------------------Para todo esclavo enviar (esclavo, &palabra, ...)---------------------------
cuentaM
Problema: Número de ocurrencias de (un dato)* en array grande
cuentaM
cuentaE1 cuentaEncuentaE2
“Ala”“Ala”
“Ala”
---------------------------bcast (esclavos, &palabra, ...)---------------------------
cuentaM¿Más eficiente?
¿Sincronismo?
sortM
sortE1 sortEn
VsortM
sortE1 sortEn
V
proPar Paso de mensajes entre “grupos” pasoMsj-25
• scatter ( esparcir ) y gather ( recoger ) Ej: Ordenación
scatter (V, rodaja, grupo, emisor, )
sortM y sortE
gather (V, rodaja, grupo, receptor, )
sortM y sortE
proPar Paso de mensajes entre “grupos” pasoMsj-26
int V[N];
inic(V);i=0;for (e=1; e<=nProc; e++) { enviar (e, &V[i], longRodaja); i += longRodaja;}ordenar (V, longRodaja);i=0;for (e=1; e<=nProc; e++) { recibir(e, &V[i], longRodaja); i += longRodaja;}
int R[longRodaja];
recibir (0, R, longRodaja);ordenar (V, longRodaja);enviar (0, R, longRodaja);
int *V;
if (yo==0) { V = malloc(N); inic(V); }else V = malloc(longRodaja);scatter (V, V, grupo, 0);ordenar (V, longRodaja);gather (V, V, grupo, 0);
cuentaM
cuentaE12
3
cuentaE25
cuentaEn1
proPar Paso de mensajes entre “grupos” pasoMsj-27
• reduce (recibir de unos concretos y operar) Ej: Ocurrencias
Total = veces;Para todo esclavo recibir (esclavo, &veces, ...) Total += veces;
cuentaM
reduce (+, &veces, grupo, receptor, ...)
cuentaM y cuentaE
+
máximo, mínimo, *, .....
¿Más eficiente?
proPar MPI (Introducción) pasoMsj-28
MPI: Message Passing Interface – 1994 MPI Forum [Nov/92]
“Ejecución de aplicaciones paralelas distribuidas en ordenadores heterogéneos”
maestro
esclavo1 esclavo3esclavo2 esclavo4
Cada uno con su dirIP
• Biblioteca “mpi.h”
MPI_Send,
MPI_Recv,
-------------
M E1 E2 E3 E4
• Implementación
MPICH
LAM/MPI
IBM, …
MPI-2
MPI-3
>= 0 => MPI_SUCCESS, significado concreto
< 0 => un error ( ... MPI_ERR_ARG ...)
proPar MPI (Procesos) pasoMsj-29
int MPI_Comm_size(…, int *numProcesos);
int MPI_Comm_rank(…, int *yo);
int MPI_Finalize();
int MPI_Init( ....... ); /* Inicia MPI */
• Creación estática de procesos (según implementación “mpirun”)
01
3
2
4
MPI_COMM_WORLD
2
5
2
proPar MPI (Procesos) pasoMsj-30
• helloWorld paralelo#include “mpi.h”int main (int argc, char *argv[]) { int yo, numProcesos;
MPI_Init (&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &numProcesos); MPI_Comm_rank (MPI_COMM_WORLD, &yo); if (yo == 0) printf (“Creados %d procesos\n”, numProcesos); printf (“Hola, soy el proceso %d\n”, yo); MPI_Finalize();}
% mpirun –np 3 helloWorld
% mpirun –p4pg helloWorld.txt helloWorld
pc1 2 /usuarios/alumnosPropar/propar01/p1/helloWorldpc2 2 /usuarios/alumnosPropar/propar01/p1/helloWorldpc3 1 /usuarios/alumnosPropar/propar01/p1/holaMundo
proPar MPI (Envío y Recepción Simple) pasoMsj-31
• Enviar y recibir arrays de datos simples (int, byte, ...) Bloqueante
int vector[N];----------MPI_Send (vector, … P2, ...)----------
P1
int tabla[M];----------MPI_Recv (tabla, … P1, ...)----------
P2
int MPI_Send(void *buffer, int cuantos, MPI_Datatype tipo,
int destino, int etiqueta, MPI_Comm grupo)
MPI_INT,MPI_FLOAT, …
MPI_COMM_WORLD
0..MPI_TAG_UB
proPar MPI (Envío y Recepción Simple) pasoMsj-32
• Enviar y recibir arrays de datos simples (int, byte, ...) Bloqueante
int MPI_Recv(void *buffer, int cuantos, MPI_Datatype tipo,
int remitente,int etiqueta,MPI_Comm grupo,
MPI_Status *estado)
estado.MPI_SOURCEestado.MPI_TAG
MPI_ANY_SOURCE
MPI_ANY_TAG
int MPI_Get_count( MPI_Status *estado, MPI_Datatype tipo,
int *cuantos)
proPar MPI (Envío y Recepción Simple) pasoMsj-33
• Ejemplo de uso: psendrec.c
#include <stdio.h>#include <unistd.h>
#include “mpi.h"
#define N 3#define VECES 5
void esclavo(void) {...}void maestro(void) {...}
int main( int argc, char *argv[] ) { int yo; MPI_Init (&argc, &argv); MPI_Comm_rank (MPI_COMM_WORLD, &yo); if (yo == 0) maestro(); else esclavo(); MPI_Finalize(); return 0;}
proPar MPI (Envío y Recepción Simple) pasoMsj-34
• Ejemplo de uso: psendrec.c
void maestro (void) {
int i, j, vector[N];
for (i=0; i<VECES; i++) { printf ("M: envia => "); for (j=0; j<N; j++) { vector[j] = i*N+j; printf("%d ", vector[j]); } printf ("\n"); MPI_Send (vector, N, MPI_INT, 1, 1, MPI_COMM_WORLD); }}
esclavo
proPar MPI (Envío y Recepción Simple) pasoMsj-35
• Ejemplo de uso: psendrec.c
void esclavo(void) {
int i, j,tabla[N], n; MPI_Status estado;
sleep(2); for (i=0; i<VECES; i++) { MPI_Recv (tabla, N, MPI_INT, 0, 1, MPI_COMM_WORLD, &estado); MPI_Get_count (&estado, MPI_INT, &n); printf ("E: recibe => "); for (j=0; j<N; j++) printf("%d ", tabla[j]); printf (" de tid = %d eti = %d longi = %d\n", estado.MPI_SOURCE, estado.MPI_TAG, n); }}
maestro
proPar MPI (Envío y Recepción No Tan Simple) pasoMsj-36
int MPI_Iprobe(int origen, int etiqueta, MPI_Comm grupo, int *hayMsj, MPI_Status *estado)
• Enviar y recibir arrays de datos simples No Bloqueante
• Enviar y recibir datos no homogéneos
Crear tipos => Algo tedioso
Hacer otras cosas
NO
int MPI_Recv(void *buffer,… MPI_Status *estado)
SI
proPar MPI (Comunicación colectiva) pasoMsj-37
int MPI_Bcast(void *buffer, int cuantos,
MPI_Datatype tipo, int emisor,
MPI_Comm grupo)
cuenta.0
cuenta.1 cuenta.Ncuenta.2
“Ala”“Ala”
“Ala”
void maestro () { void esclavo () { char palabra[4]; char texto[4]; ---------- ---------- MPI_Bcast ( MPI_Bcast ( palabra, 4, MPI_CHAR, texto, 4, MPI_CHAR, 0, MPI_COMM_WORLD); 0, MPI_COMM_WORLD); ---------- ----------
?tag
Send+Recv
proPar MPI (Comunicación colectiva) pasoMsj-38
int MPI_Scatter(
void *vOrg, int nOrg, MPI_Datatype tOrg,
void *vDst, int nDst, MPI_Datatype tDst,
int emisor, MPI_Comm grupo);
grupoE.1 grupoE.9
grupoM.0
int MPI_Reduce(void *vOrg, void *vDst, int nOrg,
MPI_Datatype tDatoOrg, int operacion,
int receptor, MPI_Comm grupo);
+
MPI_SUM, MPI_PROD, MPI_MIN, MPI_MAX, ....
sendCount
proPar MPI (Comunicación colectiva: Ejemplo) pasoMsj-39
• Ejemplo de uso completo: cuentaPar2.c (modelo SPMD)
#include <stdio.h>
#include “mpi.h"
#define CARDINALIDAD 2000000#define MAX_ENTERO 1000#define NUM_BUSCADO 5
int main( int argc, char *argv[] ) {
int i, numVeces, numVecesTotal, yo; int longRodaja, numProcesos; int *vector;
MPI_Init (&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &numProcesos); MPI_Comm_rank (MPI_COMM_WORLD, &yo); --------------------------- MPI_Finalize();}
proPar MPI (Comunicación colectiva: Ejemplo) pasoMsj-40
• Ejemplo de uso completo: cuentaPar2.c
// Pedir memoria vector e inicializarlo si maestrolongRodaja = CARDINALIDAD / numProcesos;if (yo == 0) { vector = malloc (CARDINALIDAD * 4); for (i=0; i<CARDINALIDAD; i++) vector[i] = random() % MAX_ENTERO;} else vector = malloc (longRodaja * 4);
MPI_Scatter (vector, longRodaja, MPI_INT, vector, longRodaja, MPI_INT, 0, MPI_COMM_WORLD);// Todos buscan en su trozonumVeces = 0;for (i=0; i<longRodaja; i++) if (vector[i] == NUM_BUSCADO) numVeces++;MPI_Reduce (&numVeces, &numVecesTotal, 1, MPI_INT, MPI_SUM, 0 , MPI_COMM_WORLD);if (yo == 0) printf (“Numero de veces => %d\n”, numVecesTotal);
proPar MPI (Comunicación colectiva) pasoMsj-41
• Otras llamadas interesantes:
int MPI_Gather(void *vOrg, int nOrg, MPI_Datatype tOrg,
void *vDst, int nDst, MPI_Datatype tDst,
int receptor, MPI_Comm grupo);
int MPI_Barrier(MPI_Comm grupo);
----------MPI_Comm_size (MPI_COMM_WORLD, &numProcesos);----------// Computar todos paso 1
MPI_Barrier (MPI_COMM_WORLD);
// Computar todos paso 2
6
proPar Evaluación de programas paralelos pasoMsj-42
• ¿Cuánto tardará mi programa paralelo TP?
• Medición experimental
• Estudio analítico
Codificar, Depurar, Probar, ...
Modelo imperfecto, aproximado
m
e0 e9
cuentaVeces:
• V[1.000.000]
• 10 esclavos
TP = TCPU + TRED
a. Enviar rodajas TRED
c. Recibir veces TRED
b. Contar veces TCPU
veces = 0;for (i=0; i<N’; i++) if (rodaja[i] == D) veces++;
N’ N
N’ * (#i * Tinst) O (N) | O (N2) | O (NlogN) | O(logN)
proPar Evaluación de programas paralelos pasoMsj-43
#m * (TL + #d * TD)#d
t
TL
TP = TCPU + TRED
N’ * (#i * Tinst)
Ejemplos
T3D+PVM
IBM PS2+MPI
iacluster+MPI 40s
35s
3s
TL
64ns
230ns
63ns
TD[8B]
0,6ns
4,2ns
11ns
Tinst
66666
8333
273
TL
107
55
6
TD
1
1
1
Tinst
Normalizar
TP = TCPU + TREDSolapar tiempos | ocultar latencias
Comunicación asíncrona
#msj,
tamaño(#d),
topología red,
tecnología, ...
proPar Evaluación de programas paralelos pasoMsj-44
• Ejemplo: cuentaVeces, V[1.000.000], 10 esclavos
T1 = 1.000.000 * (#i * Tinst)
T10 = TRED(10Rodajas) + TCPU(100.000) + TRED(10Resultados)
T3D: TL(273) y TD(6)
T10 = 10*(273+100.000*6) + 100.000*#i*1 + 10*(273+6) = 6.005.520 + 100.000#i
S10 = 1.000.000*#i / (6.005.520+100.000#i)
iacluster: TL(66.666) y TD(64)
T10 = ... 66.666 ... 64 + ...*1 + ... 66.666+64 = 65.333.960 + 100.000#i
S10 = 1.000.000*#i / (65.333.960 +100.000#i)
#i S10
50 0,71
100 1,33500 4,34
#i S10
5 0,8
10 1,4500 8,9
proPar Herramientas de depuración y monitorización pasoMsj-45
• Medición de tiempos de ejecución
• Depuración
• Monitorización
#include <sys/time.h>
struct timeval t0, tf, tiempo;
/* Inicialización */
gettimeofday (&t0, NULL);
/* ejecucion del programa paralelo */
gettimeofday (&tf, NULL); timersub (&tf, &t0, &tiempo); printf (“Tiempo => %ld:%ld seg:micro\n”, tiempo.tv_sec, tiempo.tv_usec);
Evitar E/S
¿Efecto del optimizador de código?
gcc –O3
proPar Herramientas de depuración y monitorización pasoMsj-46
%mpirun –dbg=ddd –np 2 psendrec
Depurar más de un proceso,
algo más complejo
printf
fflush(stdout)
setbuf(stdout, NULL)
depurar (ddd)
proPar Herramientas de depuración y monitorización pasoMsj-47
• Monitorización (XPVM) para PVM
proPar Herramientas de depuración y monitorización pasoMsj-48
• Monitorización (totalview) para MPI, openMP, … www.etnus.com
www.roguewave.com
proPar Herramientas de depuración y monitorización pasoMsj-49
• Monitorización VAMPIR www.vampir.eu
FIN