La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

proPar Curso 13/14 4 2, 3, 2 2, 2 5 Computadores Paralelos

Presentaciones similares


Presentación del tema: "proPar Curso 13/14 4 2, 3, 2 2, 2 5 Computadores Paralelos"— Transcripción de la presentación:

1 proPar Curso 13/14 4 2, 3, 2 2, 2 5 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 Algoritmos y aplicaciones Ordenación, …

2 Procesamiento Paralelo Temario pasoMsj-2
PROGRAMACIÓN BASADA EN PASO DE MENSAJES Recordar concurrencia pthreads: contar y ordenar Un modelo de paso de mensajes Opciones de programación Creación de procesos Rutinas genéricas de paso de mensajes MPI Introducción Procesos Envío y recepción de mensajes Comunicación colectiva Evaluación de programas paralelos Herramientas de depuración y monitorización

3 proPar Recordar concurrencia pthreads pasoMsj-3
contarPar.c: Número de apariciones de un número en un vector const N = 40; objetivo = 6; numCPUs = 4; var vector array[1..N] of integer; T1 T2 T3 T4 1 3 2 + 8 ¿ Algoritmo paralelo ?

4 proPar Recordar concurrencia pthreads pasoMsj-4
int 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); 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

5 proPar Recordar concurrencia pthreads pasoMsj-5
// Variables globales int 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); }

6 proPar Recordar concurrencia pthreads pasoMsj-6
cuentaPar // Recorriéndolo diez veces 2 Xeon E5520 Quad 2,26GHz • 8ML3 • 12GB • 500GB Esclavos Tiempo Aceleración Eficiencia 1 5,480 2 2,721 2,01 1,01 4 1,408 3,89 0,97 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

7 proPar Recordar concurrencia pthreads pasoMsj-7
sortPar.c: Ordenar un vector en memoria ordenar T1 T2 T3 T4 T1 T3 mezclar T1 mezclar

8 proPar Recordar concurrencia pthreads pasoMsj-8
sortPar.c: Ordenar un vector en memoria [Refinamiento] La mezcla es destructiva => vector auxiliar Va Vb ? A B C D E F G 1 2 3 4 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; Mezclar requiere haber ordenado … => semáforos

9 proPar Recordar concurrencia pthreads pasoMsj-9
#define MAX_ENTERO #define MAX_ESCLAVOS // 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++];

10 proPar Recordar concurrencia pthreads pasoMsj-10
void *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);

11 proPar Recordar concurrencia pthreads pasoMsj-11
int 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); pthread_join (pids[i], NULL); return (0); } sort => 8:350 sortPar => 2:100

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

13 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

14 proPar Opciones de programación pasoMsj-14
Diseño específico de un lenguaje: Occam  Transputer Extensión de lenguaje existente: Fortran M, CC++, Cilk++ www-unix.mcs.anl.gov/dbpp/text/node51.html OpenMP Biblioteca de paso de mensajes sobre C, Fortran, C++ PVM: MPI: www-unix.mcs.anl.gov/mpi HPC++: Paralelización automática: El compilador extrae paralelismo del código secuencial ¿ Sistema Operativo ?

15 proPar Opciones … (TRANSPUTER) pasoMsj-15
1979 Proyecto Europeo: Inmos SGS-Thomson ICL ... † Objetivo: µP de altas prestaciones, como elemento básico para construir máquinas paralelas (multicomputadores) 1992: habían vendido unidades (µP+1MB => pts) Característica relevante: 4 enlaces de comunicación (canales) T800 1 2 3 Ejecución eficiente de n procesos que envían/reciben mensajes por canales P1 P2 P3 cP3 ! dato cP2 ? dato

16 proPar Opciones… (Placa de desarrollo para PC) pasoMsj-16
TRAM slots Slot 9 IMS C004 Link switch IMS T222 1 2 5 6 4 7 3 8 Tarjeta IMS B008 SubSystem sockets pts 1992 PC Bus Interface Slot 0 Slot 1 Slot 2 Slot 9 2 1 1 3 config reset

17 proPar Creación de procesos pasoMsj-17
¿Cómo podría ser contarPar.c si no hay memoria común? maestro 6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 … El vector lo tiene un proceso “maestro” 1 3 2 6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 … + 8 6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 … 1 3 2 esclavo1 esclavo2 esclavo3 esclavo4 2 tipos distintos de procesos El maestro: reparte “envía” trabajo a los “esclavos” y recoge “recibe” resultados

18 proPar Creación de procesos pasoMsj-18
¿Cómo podría ejecutarse la aplicación? maestro esclavo1 esclavo2 esclavoN maestro.exe esclavo.exe Un proceso x núcleo M E maestro.c esclavo.c maestro.exe esclavo.exe ¿Arquitecturas distintas? Multiple Program Multiple Data MPMD Dos ejecutables: maestro.exe y esclavo.exe Creación de procesos: estática vs dinámica

19 proPar Creación de procesos (creación dinámica) pasoMsj-19
MPMD: Multiple Program Multiple Data spawn (“esclavo”, 4, ...) maestro.c contarEnTrozo (......) esclavo.c maestro esclavo %pvm pvm>add PC pvm>spawn maestro M E

20 proPar Creación de procesos (creación estática) pasoMsj-20
SPMD: Single Program Multiple Data if (miIdProceso == 0) maestro() else esclavo() sort.c programa fuente M E 1 8 *.exe %mpirun –np 9 sort %mpirun –p4pg fiConf sort

21 proPar Creación de procesos pasoMsj-21
A veces, viene bien que el maestro también trabaje esclavo1 esclavo2 esclavo3 maestro0 6 2 0 … 0 6 7 … 6 2 5 … 2 1 7 … 1 3 2 Modelo SPMD y creación de procesos estática

22 proPar Rutinas genéricas de paso de mensajes pasoMsj-22
Pi.enviar(Pj, &msj, ...)  Pj.recibir(Pi, &msj, ...) enviar (esclavo, &rodaja[k], ...) sortM recibir (maestro, &miRodaja, ...) sortE Máquina PID_Local enviar( Pi, &msj, temporización, ) t Varias semánticas: Bloqueante (Síncrona | Rendezvous) No bloqueante (Asíncrona: Capacidad de almacenar) Temporizada (Tiempo máximo de bloqueo)

23 proPar Rutinas genéricas de paso de mensajes pasoMsj-23
Bloqueante vs NoBloqueante ¿ Dónde ? enviar... recibir... enviar... recibir... Buffer Gestión de buffers El primero se bloquea Transferencia sin buffers adicionales Se sabe que se ha recibido Se desacopla env | rec ¿Se ha recibido? => msjACK enviar( Pi, &msj, temporización, ...)

24 proPar Rutinas genéricas de paso de mensajes pasoMsj-24
recibirDeCualquiera (&msj) | recibir ( -1, &msj) sortE1 sortEn sortM quien = recibir (-1, &rodaja[k], ...) sortM Mensajes etiquetados Cliente Servidor H P P P P P P P enviar (S, &msj, tipoP) enviar (S, &msj, tipoH) recibir (-1, &msj, tipoH) recibir (-1, &msj, )

25 proPar Paso de mensajes entre “grupos” pasoMsj-25
Broadcast (a todos) Multicast (a unos concretos) Problema: Número de ocurrencias de (un dato)* en array grande cuentaM cuentaE1 cuentaEn cuentaE2 “Ala” Para todo esclavo enviar (esclavo, &palabra, ...) cuentaM ¿Más eficiente? bcast (esclavos, &palabra, ...) cuentaM

26 proPar Paso de mensajes entre “grupos” pasoMsj-26
scatter ( esparcir ) y gather ( recoger ) Ej: Ordenación sortM sortE1 sortEn V sortM sortE1 sortEn V scatter (V, rodaja, grupo, emisor, ) sortM y sortE gather (V, rodaja, grupo, receptor, ) sortM y sortE

27 proPar Paso de mensajes entre “grupos” pasoMsj-27
reduce (recibir de unos concretos y operar) Ej: Ocurrencias cuentaM cuentaE1 2 3 cuentaE2 5 cuentaEn 1 reduce (+, &veces, grupo, receptor, ...) cuentaM y cuentaE + Total = veces; Para todo esclavo recibir (esclavo, &veces, ...) Total += veces; cuentaM máximo, mínimo, *, .....

28 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 esclavo3 esclavo2 esclavo4 MPI-2 Biblioteca “mpi.h” MPI_Send, MPI_Recv, Implementación MPICH LAM/MPI IBM, … M E1 E2 E3 E4 Cada uno con su dirIP

29 proPar MPI (Procesos) pasoMsj-29
Creación estática de procesos (según implementación “mpirun”) 1 3 2 4 MPI_COMM_WORLD >= 0 => MPI_SUCCESS, significado concreto < 0 => un error ( ... MPI_ERR_ARG ...) int MPI_Comm_size(…, int *numProcesos); int MPI_Comm_rank(…, int *yo); int MPI_Finalize(); int MPI_Init( ); /* Inicia MPI */ 5 2 2

30 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/helloWorld pc2 2 /usuarios/alumnosPropar/propar01/p1/helloWorld pc3 1 /usuarios/alumnosPropar/propar01/p1/holaMundo

31 proPar MPI (Envío y Recepción Simple) pasoMsj-31
Enviar y recibir arrays de datos simples (int, byte, ...) Bloqueante P1 P2 int vector[N]; MPI_Send (vector, … P2, ...) int tabla[M]; MPI_Recv (tabla, … P1, ...) 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

32 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) MPI_ANY_SOURCE MPI_ANY_TAG estado.MPI_SOURCE estado.MPI_TAG int MPI_Get_count( MPI_Status *estado, MPI_Datatype tipo, int *cuantos)

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

34 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

35 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

36 proPar MPI (Envío y Recepción No Tan Simple) pasoMsj-36
Enviar y recibir arrays de datos simples No Bloqueante int MPI_Iprobe(int origen, int etiqueta, MPI_Comm grupo, int *hayMsj, MPI_Status *estado) Hacer otras cosas NO int MPI_Recv(void *buffer,… MPI_Status *estado) SI Enviar y recibir datos no homogéneos Crear tipos => Algo tedioso

37 proPar MPI (Comunicación colectiva) pasoMsj-37
cuenta.0 cuenta.1 cuenta.N cuenta.2 “Ala” int MPI_Bcast(void *buffer, int cuantos, MPI_Datatype tipo, int emisor, MPI_Comm grupo) Send+Recv ? tag 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); , MPI_COMM_WORLD);

38 proPar MPI (Comunicación colectiva) pasoMsj-38
sendCount 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 + MPI_SUM, MPI_PROD, MPI_MIN, MPI_MAX, .... int MPI_Reduce(void *vOrg, void *vDst, int nOrg, MPI_Datatype tDatoOrg, int operacion, int receptor, MPI_Comm grupo);

39 proPar MPI (Comunicación colectiva: Ejemplo) pasoMsj-39
Ejemplo de uso completo: cuentaPar2.c (modelo SPMD) #include <stdio.h> #include “mpi.h" #define CARDINALIDAD #define MAX_ENTERO #define NUM_BUSCADO 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(); }

40 proPar MPI (Comunicación colectiva: Ejemplo) pasoMsj-40
Ejemplo de uso completo: cuentaPar2.c // Pedir memoria vector e inicializarlo si maestro longRodaja = 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 trozo numVeces = 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);

41 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

42 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 N’ N TP = TCPU + TRED m e0 e9 cuentaVeces: V[ ] 10 esclavos Enviar rodajas TRED Recibir veces TRED veces = 0; for (i=0; i<N’; i++) if (rodaja[i] == D) veces++; Contar veces TCPU N’ * (#i * Tinst) O (N) | O (N2) | O (NlogN) | O(logN)

43 proPar Evaluación de programas paralelos pasoMsj-43
TP = TCPU + TRED N’ * (#i * Tinst) #d t TL #msj, tamaño(#d), topología red, tecnología, ... #m * (TL + #d * TD) 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 Tinst Normalizar Solapar tiempos | ocultar latencias Comunicación asíncrona TP = TCPU + TRED

44 proPar Evaluación de programas paralelos pasoMsj-44
Ejemplo: cuentaVeces, V[ ], 10 esclavos T1 = * (#i * Tinst) T10 = TRED(10Rodajas) + TCPU( ) + TRED(10Resultados) T3D: TL(273) y TD(6) T10 = 10*( *6) *#i*1 + 10*(273+6) = #i S10 = *#i / ( #i) #i S10 5 0,8 10 1,4 500 8,9 iacluster: TL(66.666) y TD(64) T10 = * = #i S10 = *#i / ( #i) #i S10 50 0,71 100 1,33 500 4,34

45 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); ¿Efecto del optimizador de código? gcc –O3 Evitar E/S

46 proPar Herramientas de depuración y monitorización pasoMsj-46
%mpirun –dbg=ddd –np 2 psendrec depurar (ddd) printf fflush(stdout) setbuf(stdout, NULL) Depurar más de un proceso, algo más complejo

47 proPar Herramientas de depuración y monitorización pasoMsj-47
Monitorización (XPVM) para PVM

48 proPar Herramientas de depuración y monitorización pasoMsj-48
Monitorización (totalview) para MPI, openMP, … FIN


Descargar ppt "proPar Curso 13/14 4 2, 3, 2 2, 2 5 Computadores Paralelos"

Presentaciones similares


Anuncios Google