proParCurso 14/15

49
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

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

Transcript of proParCurso 14/15

Page 1: proParCurso 14/15

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

Page 2: proParCurso 14/15

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

Page 3: proParCurso 14/15

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

Page 4: proParCurso 14/15

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

Page 5: proParCurso 14/15

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

Page 6: proParCurso 14/15

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

Page 7: proParCurso 14/15

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

Page 8: proParCurso 14/15

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

Page 9: proParCurso 14/15

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

Page 10: proParCurso 14/15

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()

Page 11: proParCurso 14/15

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

Page 12: proParCurso 14/15

proPar Opciones de programación pasoMsj-12Entornos de programación paralela en los 90 “Tim Mattson - Intel”

Page 13: proParCurso 14/15

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

Page 14: proParCurso 14/15

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

Page 15: proParCurso 14/15

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

Page 16: proParCurso 14/15

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

Page 17: proParCurso 14/15

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 ?

Page 18: proParCurso 14/15

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

Page 19: proParCurso 14/15

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

Page 20: proParCurso 14/15

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

Page 21: proParCurso 14/15

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

Page 22: proParCurso 14/15

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, ...)

Page 23: proParCurso 14/15

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

Page 24: proParCurso 14/15

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?

Page 25: proParCurso 14/15

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

Page 26: proParCurso 14/15

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

Page 27: proParCurso 14/15

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?

Page 28: proParCurso 14/15

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

Page 29: proParCurso 14/15

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

Page 30: proParCurso 14/15

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

Page 31: proParCurso 14/15

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

Page 32: proParCurso 14/15

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)

Page 33: proParCurso 14/15

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;}

Page 34: proParCurso 14/15

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

Page 35: proParCurso 14/15

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

Page 36: proParCurso 14/15

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

Page 37: proParCurso 14/15

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

Page 38: proParCurso 14/15

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

Page 39: proParCurso 14/15

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();}

Page 40: proParCurso 14/15

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

Page 41: proParCurso 14/15

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

Page 42: proParCurso 14/15

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)

Page 43: proParCurso 14/15

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

Page 44: proParCurso 14/15

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

Page 45: proParCurso 14/15

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

Page 46: proParCurso 14/15

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)

Page 47: proParCurso 14/15

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

• Monitorización (XPVM) para PVM

Page 48: proParCurso 14/15

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

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

www.roguewave.com

Page 49: proParCurso 14/15

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

• Monitorización VAMPIR www.vampir.eu

FIN