MODELO PASO DE MENSAJES

48
proPar Curso 14/15 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

Transcript of MODELO PASO DE MENSAJES

proPar Curso 14/15

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 ordenar

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

• sortPar.c: Ordenar un vector en memoria

3 8 15 2 4 1 7 10 6 14 13 5 11 9 12 16

T1 T2 T3 T4

2 3 8 15 1 4 7 10 5 6 13 14 9 11 12 16

ordenar

1 2 3 4 7 8 10 15 5 6 9 11 12 13 14 16

T1 T3mezclar

T1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

mezclar

proPar Recordar concurrencia pthreads pasoMsj-8

• sortPar.c: Ordenar un vector en memoria [Refinamiento]

A B C D

E F

G

1 2 3 4

1 3

1

esclavo (yo: integer);

ordenarRodaja(yo); case yo of 1: mezclar(A,B,E); mezclar(E,F,G); 2: ; 3: mezclar(C,D,F); 4: ; end;

?

1. La mezcla es destructiva => vector auxiliar

Va

Va

Vb

Va

2 Mezclar requiere haber ordenado … => semáforos

proPar Recordar concurrencia pthreads pasoMsj-9#define MAX_ENTERO 10000#define MAX_ESCLAVOS 4 // Solo funciona con 4 esclavos

//-------------- VARIABLES GLOBALES ------------------------------- int cardinalidad, longRodaja; int *vector, *vectorBis; sem_t S2a1, S4a3, S3a1;

void imprimir (int *vector) { int i;

printf ("Contenido del vector\n"); printf ("====================\n"); for (i=0; i<cardinalidad; i++) { printf ("%6d ", vector[i]); if ((i%10) == 0) printf ("\n"); } printf ("\n");}

void mezclar (int i, int longRodaja, int *vOrg, int *vDst) { int iDst, iTope, j, jTope;

iTope = i + longRodaja; j = iTope; jTope = j + longRodaja; for (iDst = i; iDst < jTope; iDst++) { if (i == iTope ) vDst[iDst] = vOrg[j++]; else if (j == jTope ) vDst[iDst] = vOrg[i++]; else if (vOrg[i] < vOrg[j]) vDst[iDst] = vOrg[i++]; else vDst[iDst] = vOrg[j++]; }}

proPar Recordar concurrencia pthreads pasoMsj-10void *esclavo(void *parametro) { int yo, inicio, fin, i, j, imenor, menor; int unCuarto, unMedio;

yo = (int) parametro; inicio = yo * longRodaja; fin = inicio + longRodaja; unMedio = cardinalidad / 2; unCuarto = cardinalidad / 4;

// Ordenar por insercion directa for (i = inicio; i < fin; i++) { imenor = i; menor = vector[i]; for (j = i; j < fin; j++) if (vector[j] < menor) { imenor = j; menor = vector[j]; } vector[imenor] = vector[i]; vector[i] = menor; }

// Fase de mezclas. Solo valida para 4 esclavos switch (yo) { case 0: sem_wait (&S2a1); mezclar(0, unCuarto, vector, vectorBis); sem_wait (&S3a1); mezclar(0, unMedio, vectorBis, vector); break; case 1: sem_post (&S2a1); break; case 2: sem_wait (&S4a3); mezclar(unMedio, unCuarto, vector, vectorBis); sem_post (&S3a1); break; case 3: sem_post (&S4a3); break; default: printf ("Error\n"); break; } pthread_exit(NULL);}

proPar Recordar concurrencia pthreads pasoMsj-11int main( int argc, char *argv[] ) { int i, numEsclavos; pthread_t pids[MAX_ESCLAVOS];

cardinalidad = atoi(argv[1]); numEsclavos = MAX_ESCLAVOS; longRodaja = cardinalidad / numEsclavos;

// Pedir memoria e inicializar el vector vector = malloc(cardinalidad * sizeof(int)); vectorBis = malloc(cardinalidad * sizeof(int)); for (i=0; i<cardinalidad; i++) vector[i] = random() % MAX_ENTERO; imprimir(vector);

// Inicializar semaforos para sincronizar sem_init (&S2a1, 0, 0); sem_init (&S4a3, 0, 0); sem_init (&S3a1, 0, 0);

// 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);

imprimir(vector); return (0);}

sort 200000 => 8:350sortPar 200000 => 2:100

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?

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?

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

cuentaM

cuentaE12

3

cuentaE25

cuentaEn1

proPar Paso de mensajes entre “grupos” pasoMsj-26

• 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, *, .....

proPar MPI (Introducción) pasoMsj-27

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-28

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-29

• 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-30

• 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-31

• 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-32

• 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-33

• 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-34

• 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-35

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-36

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-37

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-38

• 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-39

• 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-40

• 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-41

• ¿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-42

#m * (TL + #d * TD)#d

t

TL

TP = TCPU + TRED

N’ * (#i * Tinst)

Ejemplos

T3D+PVM

IBM PS2+MPI

iacluster+MPI 40µs

35µs

3µs

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-43

• 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-44

• 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-45

%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-46

• Monitorización (XPVM) para PVM

proPar Herramientas de depuración y monitorización pasoMsj-47

• Monitorización (totalview) para MPI, openMP, … www.etnus.com

www.roguewave.com

proPar Herramientas de depuración y monitorización pasoMsj-48

• Monitorización VAMPIR www.vampir.eu

FIN