Descargar la presentación
La descarga está en progreso. Por favor, espere
Publicada porMauro Anjos de Mendonça Modificado hace 6 años
1
proPar Curso 18/19 5 3 2, 3, 2 2, 2 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 Algoritmos y aplicaciones Ordenación, …
2
proPar Temario diviVence-2
Particionamiento y Divide y Vencerás Particionamiento Divide y Vencerás Ordenación mediante cubetas Integración numérica Problema de los N-cuerpos
3
proPar Particionamiento diviVence-3
Particionar: Dividir el problema en partes (Ej: Fractal Mandelbrot) datos cuentaM cuentaE1 cuentaEn funcional f1 f2 fn Mucho menos frecuente Huffman Quantizar IDCT P B YCbCr RGB MPEG Componer resultado final: scatter + reduce
4
proPar Divide y Vencerás diviVence-4
Divide y Vencerás: Particionar de forma recursiva, combinando resultados (Ej: QuickSort, SumarNúmeros) int sumar(int *s) { if (card(s) <= 2) return (n1 + n2); else { dividir (s, s1, s2); suma1 = sumar(s1); suma2 = sumar(s2); return (suma1 + suma2); } + ¿ Paralelización ?
5
proPar Divide y Vencerás (paralelización) diviVence-5
Recolectar sumas Dividir P7 P8 P9 P10 P11 P12 P13 P14 P3 P4 P5 P6 P1 P2 P0 No trabajan todos los procesos todo el tiempo
6
proPar Divide y Vencerás (paralelización) diviVence-6
Nivel 4 2 1 P0 P1 P2 P3 P4 P5 P6 P7 P0 P1 P2 P3 P4 P5 P6 P7 P0 => 4, 2, 1 P4 => 6, 5 P2 => 3 P6 => 7 ¿ Cómo programarlo ? Recibir_Mi_Trozo Distribuir_A_Descendientes Procesar_Mi_Trozo Recolectar_Sumas_De_Mis_Descendientes Enviar_Mi_Suma_Total_A_Mi_Ancestro ¿De quién? ¿A cuáles?
7
proPar Divide y Vencerás (paralelización) diviVence-7
//Recibir_Mi_Trozo if (yo == 0) nivel = numProcesos / 2; else recibir (-1, {&padre, &nivel, &miTrozo}); //Distribuir_A_Descendientes for (i=nivel; i>0; i=i/2) enviar(yo+i, {yo, i/2, trozo(i)}); //Procesar_Mi_Trozo //Recolectar_Sumas_De_Mis_Descendientes //Enviar_Mi_Suma_Total_A_Mi_Ancestro if (yo == 0) printf(“Total = %d\n”, Total); else enviar(padre, Total);
8
proPar Divide y Vencerás (paralelización) diviVence-8
//Recibir_Mi_Trozo if (yo == 0) { for (i=0; i<N; i++) v[i] = random(); nivel = numProcesos / 2; longRodaja = N; } else { MPI_Recv (v, N/2, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &estado); padre = estado.MPI_SOURCE; nivel = estado.MPI_TAG; MPI_Get_count (&estado, MPI_INT, longRodaja); } //Distribuir_A_Descendientes for (i=nivel; i>0; i=i/2) { longRodaja = longRodaja / 2; MPI_Send (&v[longRodaja], longRodaja, MPI_INT, yo+i, i/2, MPI_COMM_WORLD); ¿ scatter ?
9
proPar Divide y Vencerás (paralelización) diviVence-9
//Procesar_Mi_Trozo suma = 0; for (i=0; i<longRodaja; i++) suma += v[i]; //Recolectar_Sumas_De_Mis_Descendientes for (i=nivel; i>0; i=i/2) { MPI_Recv (&sumaBis, 1, MPI_INT, MPI_ANY_SOURCE, 1, MPI_COMM_WORLD, &estado); suma += sumaBis } //Enviar_Mi_Suma_Total_A_Mi_Ancestro if (yo>0) MPI_Send (&sumaBis, 1, MPI_INT, padre, 1, …); else printf (“Suma = %d\n”, suma); ¿ reduce?
10
proPar Divide y Vencerás (paralelización) diviVence-10
números int sumaSec => 0,033 *500 17,021 sumaParBis 0,161 0,234 1,006 1,385 1,632 Scatter + Reduce Procesos sumaPar 2 0,152 4 0,222 8 0,996 16 1,382 32 1,626 ? 2 11,388 4 10,279 8 6,320 16 3,985 32 2,675 0,75 0,41 0,34 0,27 0,20
11
proPar Ordenación mediante cubetas diviVence-11
¿Ordenar exámenes? ¿Cuánto tardará en ordenar 600 exámenes? De uno en uno A B Z Un montón por letra ¡ Más rápido ! ¿ Paralelo ? ¡ Lentísimo ! ordenar juntar
12
proPar Ordenación mediante cubetas diviVence-12
DNI Edad (días) Sueldo anual ? M números ( ) en un rango (sea: ) Uniformemente distribuidos en N intervalos regulares (sean: 10) [ ], [ ],
13
proPar Ordenación mediante cubetas diviVence-13
DNI Edad (días) Sueldo anual ? M números ( ) en un rango (sea: ) Uniformemente distribuidos en N intervalos regulares (sean: 10) [ ], [ ],
14
proPar Ordenación mediante cubetas diviVence-14
DNI Edad (días) Sueldo anual ? M números ( ) en un rango (sea: ) Uniformemente distribuidos en N intervalos regulares (sean: 10) [ ], [ ], 10.000 19.999 9.999 90.000 99.999 M-1 Distribuir en cubetas Ordenar cubetas ¡ No todas iguales !
15
proPar Ordenación mediante cubetas diviVence-15
int V[ ] 10.000 19.999 9.999 90.000 99.999 M-1 Distribuir en cubetas ¿Qué hacer? Cubetas de algo (1%) int Cubetas [10][ ] int Cubetas [ ] Distribuir y ordenar cubetas ? Juntar cubetas
16
proPar Ordenación mediante cubetas diviVence-16
DNI Edad (días) Sueldo anual ? M números ( ) en un rango (sea: ) Uniformemente distribuidos en N intervalos regulares (sean: 10) [ ], [ ], 10.000 19.999 9.999 90.000 99.999 M-1 Distribuir en cubetas Ordenar cubetas ¿Programa paralelo? ¡ No todas iguales ! Juntar
17
proPar Ordenación mediante cubetas diviVence-17
Versión 1: Asociar una cubeta por proceso 10.000 19.999 9.999 90.000 99.999 M-1 P0 P1 P9 Recolectar en mi cubeta Para todo Pi ¿Con pasoMsj? Ordenar mi cubeta ¿Mejor sort+mezclas? Todos los Pi necesitan el array completo
18
proPar Ordenación mediante cubetas diviVence-18
static int *vector, elemCubeta; vector = malloc (CARDINALIDAD * 4); enterosCubeta = MAX_ENTERO / numCubetas; if (yo == 0) // Inicializar vector MPI_Bcast (vector, CARDINALIDAD, MPI_INT, 0, MPI_COMM_WORLD); // Coger los de mi cubeta elemCubeta = 0; for (i=0; i<CARDINALIDAD; i++) if ((vector[i] / enterosCubeta) == yo) vector[elemCubeta++] = vector[i]; ordenarCubeta ( ); // Enviar y Recoger cubetas if (yo == 0) { j = elemCubeta; for (i=1; i<numCubetas; i++) { MPI_Recv (&vector[j], CARDINALIDAD, MPI_INT, i, 1, MPI_COMM_WORLD, &estado); MPI_Get_count (&estado, MPI_INT, &elemCubeta); j+=elemCubeta; } } else MPI_Send (vector, elemCubeta, MPI_INT, 0, 1, MPI_COMM_WORLD);
19
proPar Ordenación mediante cubetas diviVence-19
Versión 2: Asignar un trozo del array original a cada proceso M-1 P0 P1 P9 Recolectar en miniCubetas Para todo Pi ? Env/Rec miniCubetas 10.000 19.999 9.999 90.000 99.999 Ordenar mi cubeta
20
proPar Ordenación mediante cubetas diviVence-20
Pk int miTrozo [ ] int miniCubetas [10][ ] MPI_Alltoall int cubeta [ ]
21
proPar Ordenación mediante cubetas diviVence-21
MPI_Alltoall (BufferEnvio, BufferRecepcion, MPI_Comm) buffer enviar buffer recibir P0 n-1 P1 Pn-1 Pn-1 n-1 P0 Pn-2 gather (receptorP0) gather (receptorPn-1) ¿Todas las minicubetas iguales?
22
proPar Tiempos ordenar Cubetas diviVence-22
números, cubetas/Pi y Selección Directa 97,208 puro
23
proPar Integración numérica diviVence-23
a F(x) dx b ¿Mejor trapecios? a b a b = (b – a) / N I = F(x) x=a b- Precisión ¿Cómo puede ser el programa paralelo?
24
proPar Integración numérica diviVence-24
Particionamiento y Asignación Estática (4Pi) a b a b = (b – a) / N (N= ) = (b – a) / P (P=4) P0 P1 P2 P3 Cada Pi calculará su trozo: rectángulos () ¿Esbozo del programa paralelo? Conocimiento previo del N razonable
25
proPar Integración numérica diviVence-25
int main (int argc, char *argv[]) { struct timeval t0, tf, t; double a, b, miValor, valor; int trozos, yo, numProcesos; MPI_Init (&argc, &argv); MPI_Comm_rank (MPI_COMM_WORLD, &yo); MPI_Comm_size (MPI_COMM_WORLD, &numProcesos); a = atof (argv[1]); b = atof (argv[2]); trozos = atoi (argv[3]); if (yo == 0) gettimeofday (&t0, NULL); miValor = funcion(yo, a, b, trozos, numProcesos); MPI_Reduce(&miValor, &valor, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_...); if (yo == 0) { printf ("Valor de la integral = %20.18f\n", valor); gettimeofday (&tf, NULL); timersub (&tf, &t0, &t); printf ("Tiempo = %ld:%ld (seg:mseg)\n", t.tv_sec, t.tv_usec/1000); } MPI_Finalize(); return 0;
26
proPar Integración numérica diviVence-26
double funcion (int yo, double a, double b, int trozos, int numProcesos) { double delta, valor = 0.0, miA; int i, iFin; delta = (b - a) / (double) trozos; miA = a + ((double)yo * ((b-a)/numProcesos)); printf ("%d miA = %f\n", yo, miA); iFin = trozos/numProcesos; for (i=0; i<iFin; i++) { valor += sin(miA); miA += delta; } return delta * valor; ? 1 2 4 # Tiempo 4:629 2:518 1:317 An 1,84 3,51 En 0,92 0,88 PC1: integra 1 2 4 # Tiempo 6:783 4:049 2:696 An 1,68 2,52 En 0,84 0,63 integra
27
proPar Integración numérica diviVence-27
# Tiempo An En PC9: integra Π 1 12:597 2 7:391 1,70 0,85 4 4:863 2,59 0,65 8 2:550 4,94 0,62 ¡ Igual de mal ! ¿ Mejorable ? ¡Salto de la Rana! # Tiempo An En 1 12:597 2 6:266 2,01 1,01 4 3:159 3,99 1,00 8 1:682 7,49 0,94
28
proPar Integración numérica diviVence-28
double funcion (int yo, double a, double b, int trozos, int numProcesos) { double delta, miDelta, valor = 0.0, miA; int i, iFin; delta = (b - a) / (double) trozos; miDelta = delta * (double) numProcesos; miA = a + ((double)yo * delta); printf ("%d miA = %f\n", yo, miA); iFin = trozos/numProcesos; for (i=0; i<iFin; i++) { valor += sin(miA); miA += miDelta; } return delta * valor;
29
proPar Integración numérica diviVence-29
Divide y Vencerás y Asignación Estática (4Pi) a b P0 P1 P2 P3 a b 4 A4 N Area 2 A2 = (b – a) / N (N=¿?) ¿Esbozo del programa paralelo? ¡¡ Igual que antes !! n An 2n A2n |A2n-An| < cotaError
30
proPar Integración numérica diviVence-30
miA = a + ((double)yo * ((b-a)/numProcesos)); miB = miA + ((b-a)/numProcesos); trozos = 1000; fActual = funcion(miA, miB, trozos); do { fAnterior = fActual; trozos = trozos ; } while (fabs(fActual - fAnterior) > cotaError); MPI_Reduce(&fActual, &valor, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); ? 1 2 4 # Tiempo 44:009 15:273 3:527 An 2,88 12,48 En 1,44 3,12 ? Reparto no equilibrado de trabajo Superaceleración ficticia ¿ Mejorable ?
31
proPar Integración numérica diviVence-31
trozos = 1000; fActual = funcion(yo, trozos) MPI_Reduce(&fActual, &FActual, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Bcast (&FActual, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); do { FAnterior = FActual; trozos = trozos ; fActual = funcion(yo, trozos); MPI_Reduce(&fActual, &FActual, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); } while (fabs(FActual - FAnterior) > cotaError); 1 2 4 # Tiempo 44:009 23:754 12:372 An 1,85 3,56 En 0,93 0,89 integra
32
proPar Problema de los N-cuerpos diviVence-32
“N-body” Interacción de astros en el espacio (galaxia) m1 m2 m3 m4 m2 (xi,yi) Vi i ti (xi+1,yi+1) Vi+1 i+1 ti+1 t t m (Vi+1-Vi) F = t Vi+1 = Vi + (F t / m) dist = Vi t (xi+1,yi+1) = f (dist, i, Xi, Yi) G mp mq F = F = m a r2 q p composición i+1
33
proPar Problema de los N-cuerpos diviVence-33
for (t=0; t<tMax; t++) /* Para cada periodo */ for (i=0; i<N; i++) { /* Para cada cuerpo */ FNew[i] = NuevaFuerza(i); VNew[i] = NuevaVelocidad(i); PNew[i] = NuevaPosicion(i); } for (i=0; i<N; i++){ /*Actualizar estado global*/ F[i] = Fnew[i] V[i] = VNew[i]; P[i] = PNew[i]; ¿Esbozo del programa paralelo? No computable eficientemente O(N2)
34
proPar Algoritmo de Burnes-Hut diviVence-34
Idea: Disminuir N agrupando cuerpos próximos Centro de masa r ¿ Cómo determinar las agrupaciones ?
35
proPar Algoritmo de Burnes-Hut diviVence-35
Idea: Dividir el espacio en (8 ó 4) regiones (cubos o cuadrados) que contengan un único cuerpo y luego QuadTree: Árbol cuaternario En cada nodo: Masa total Centro de masa
36
proPar Algoritmo de Burnes-Hut diviVence-36
Idea: y luego calcular (F,V,X,Y) recorriendo árbol Para Sigue r >= d / tal que = 1.0 o menor r d ¿ Parar ?
37
proPar Algoritmo de Burnes-Hut diviVence-37
38
proPar Algoritmo de Burnes-Hut diviVence-38
for (t=0; t<tMax; t++) { /* Para cada periodo */ formarArbol; CalcularMasasYCentros; CalcularNuevasFuerzas; Actualizar; } Complejidad = O(NlogN) ??? Bisección recursiva ortogonal ¿Programa paralelo? Asignar nodos a procesos Árbol muy poco equilibrado
39
proPar Algoritmo de Burnes-Hut diviVence-39
Media = 10,25
40
proPar Algoritmo de Burnes-Hut diviVence-40
Bisección recursiva ortogonal FIN
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.