Descargar la presentación
La descarga está en progreso. Por favor, espere
Publicada porValentín Cáceres Castellanos Modificado hace 10 años
1
El Cedazo de Eratosthenes Capítulo 5
2
Metas Analizar métodos de asignar bloques (“block allocation schemes”) Entender la función MPI_Bcast Estudiar métodos para mejorar rendimiento
3
El Cedazo de Erastothenes Un número primo es un entero mayor que 1 que no tiene factores ademas de 1 y si mismo. El número de primos es infinito. No hay ninguna fórmula para generar los primos Sin embargo, el matemático griego Erastothenes (276-194 BC) inventó un algoritmo para generar los primos menores que n, para cualquier entero dado n.
4
El Algoritmo de Erastothenes Secuencial 1. Crear una lista de enteros 2, 3, …, n. 2. Sea k = 2. 3. Repeat (a) Marcar todos los multiplos de k entre k 2 y n (b) Sea k el entero no marcado menor que es mayor que k until k 2 > n 4. Los números no marcados son primos.
5
Ejemplo 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 ■ multiplos de 2 ■ multiplos de 3 ■ multiplos de 5 ■ multiplos de 7
6
Estructura de Datos para el Algoritmo Secuencial Usar un arreglo booleano con n-1 elementos Elementos i, 0,1,…,n-2, representan 2,3,…,n, respectivamente Elemento en posición i, i=0,1,…,n-2, es 1 si y solo si el número i+2 se ha marcado, es decir, es un número compuesto.. Inicialmente todas las posiciones son 0, es decir ningun número está marcado.
7
Descomposición de Dominio Particionar el arreglo en n-1 pedazos. Luego, para cada k, se puede buscar los multiplos de k entre k 2 y n en paralelo Mucho paralelismo, pero muchas comunicaciones pues En el próximo paso, hay que usar una reducción-min para deteminar el menor número no marcado y una emisión para avisar todas las tareas lo que es
8
Descomposición en Bloques Dividir el arreglo en p bloques de aproximadamente el mismo tamaño de tal forma que se puede computar “facilmente” lo siguiente: Dado un valor de i, determinar el rango de datos que el proceso #i maneja Dado un elemento del arreglo de datos, determinar el proceso que lo maneja.
9
Método 1 Si n = 0 mod p, dividir los n datos en bloques de tamaño n/p. Si n ≠ 0 mod p y si n = pq + r para enteros q y r, 0<r<p, entonces asignar bloques de tamaño n/p a los primeros r procesos y bloques de tamaño n/p a los otros p-r procesos. (Note que si n=pq+r, donde 0<r<p, entonces n/p=q+r/p y por lo tanto r n/p + (p-r) n/p = r(q+1) + (p-r)q = r + pq = n)
10
Ejemplo del Método 1 n = 213 y p=8. 212 = 8 x 26 + 5 Se asignan a los procesos 0,1,2,3,4 bloques de tamaño 27 y a los procesos 5,6,7 bloques de tamaño 26.
11
Ejemplo del Método 1 (contd) Proceso 0 maneja a a 0,a 1,a 2, …, a 26 Proceso 1 maneja a a 27,a 28,a 29, …, a 53 Proceso 2 maneja a a 54,a 55,a 56, …, a 80 Proceso 3 maneja a a 81,a 82,a 83, …, a 107 Proceso 4 maneja a a 108,a 109,a 110, …, a 134 Proceso 5 maneja a a 135,a 136,a 137, …, a 160 Proceso 6 maneja a a 161,a 162,a 163, …, a 186 Proceso 7 maneja a a 187,a 188,a 189, …, a 212
12
Rango y Número de Proceso para el Método 1 El primer dato manejado por el Proceso #i es i n/p + min(i,r) y el último es (i+1) n/p + min(i+1,r)-1, donde n es el número de datos, p es el número de procesos y r es el residuo cuando n se divide entre p. El proceso que maneja al dato a j es min( j / ( n/p +1) , (j-r)/ n/p )
13
Método 2 El primer dato manejado por el dato a i es i n/p y el último es (i + 1) n/p -1 El proceso que maneja al dato a j es (p (j+1)-1)/ n
14
Ejemplo de Método 2 Proceso 0 maneja a a 0, …, a 25 Proceso 1 maneja a a 26, …, a 52 Proceso 2 maneja a a 53, …, a 78 Proceso 3 maneja a a 79, …, a 105 Proceso 4 maneja a a 106, …, a 132 Proceso 5 maneja a a 133, …, a 158 Proceso 6 maneja a a 159, …, a 185 Proceso 7 maneja a a 186, …, a 212
15
Comparación de Tamaños de Bloque para los dos Métodos Proceso Tamaño de Bloque Método 1 Tamaño de Bloque Método 2 0 27 26 1 27 2 26 3 27 4 5 26 6 27 7 26 27 P=P= p=8 n=213
16
Comparación de Cantidades de Operaciones Operación Método 1 Método 2 Indice Menor 4 2 Indice Mayor 6 4 Dueño 6 4
17
Macros La directiva #define define un identificador y una sucesión de caracteres que se sustituirá por el identificador cada vez que se encuentra en el programa. Macros pueden tener argumentos, como funciones. Para definir un macro que usa argumentos, insertar parametros entre parenteses en la definición.
18
Macros para la Descomposición en Bloques con el Método 2 #define BLOCK_LOW(id,p,n) ((id)*(n)/(p)) #define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1) #define BLOCK_SIZE(id,p,n) (BLOCK_LOW((id)+1)- BLOCK_LOW(id)) #define BLOCK_OWNER(index,p,n) (((p)*((index)+1)-1)/(n))
19
La Necesidad de Parenteses en Macros con Argumentos Son necesarias para asegurar la sustitución correcta en todos los casos. Ejemplo: #define ABS(a) (a) < 0 ? –(a) : (a) Sin parentesis, el compilador convertiria ABS(10-20) a 10-20 < 0 ? -10-20 : 10-20 cuyo valor sería -30 en vez de 10.
20
Indices Locales versus Indices Globales Cuando un solo proceso brega con un arreglo de n datos, el indice (global) varia entre 0 y n-1 Cuando p procesos brega con un arreglo de n datos, bajo la descomposición en bloques, el indice (local) varia entre 0 y el tamaño -1 del bloque que corresponde a cada proceso.
21
Comparasión de los Indices Locales y Globales Program Secuencial for (i = 0; i < n; i++) { … } Program Paralelo size = BLOCK_SIZE (id,p,n); for (i = 0; i < size; i++) { gi = i + BLOCK_LOW(id,p,n); }// gi es el indice global y i el indice // local
22
Consecuencias de la Descomposión en Bloques Si el primer proceso es responsible por los enteros hasta que y incluyendo a n, entonces se puede determinar el próximo valor de k sin ninguna comunicación. Esto occure si n/p ≥ n, es decir si p ≤ n
23
Traducción del Algoritmo Secuencial Paso 2: Cada proceso deja que k=2. Paso 3a: Cada proceso marca sus datos mayor que k 2 que son multiplos de k. Si el indice del primer multiplo es j, entonces se marca cada número en el bloque con indice de la form j+k,j+2k,j+3k,…. Paso 3b: Proceso 0 determina el próximo valor de k y emite el valor a los otros procesos.
24
La Función Bcast int MPI_Bcast ( void *buffer, /* Direccion del primer elemento */ int count, /* número de elementos para emitir */ MPI_Datatype datatype, /* Tipo de elementos */ int root, /* ID de proceso que emite */ MPI_Comm comm) /* Communicador */
25
Ejemplo de MPI_Bcast MPI_Bcast(&prime,1,MPI_INT,0,MPI_COMM_WORLD ) asigna el valor de la variable entero prime del proceso 0 a la variable primo de todos los procesos en MPI_COMM_WORLD.
26
Código del programa MPI para contar el número de primos < n #include #include "MyMPI.h" /* MyMPI.h es un archivo “header” que contiene los macros previamente discutido y los prototipos de otras funciones que vamos a desarollar */ #define MIN(a,b) ((a)<(b)?(a):(b)) /* Define el mínimo de a y b*/ int main(int argc,char *argv[]) { \* Declaraciones:*/
27
Código del Programa MPI para contar el número de primos < n (cont) int count; //Local prime count int first; //index of first multiple int global_count; //global prime count int high_value; // highest value on this processor int i; int id; //processor id int index; //index of current prime int low_value; //lowest value on this processor char *marked; //portion of 2,…,’n’ int n; //number of data int p; //number of processors int proc0_size; //size of processor 0’s subarray int prime; //current prime int size; //elements in ‘marked’
28
Código (cont) MPI_Init(&argc,&argv); //Inicialize MPI MPI_Comm_rank(MPI_COMM_WORLD,&id); //assign ranks to procs MPI_Comm_size(MPI_COMM_WORLD,&p);//find number of procs if (argc != 2) if (!id) { printf ("Command line: %s \n", argv[0]); MPI_Finalize(); exit (1); } n = atoi(argv[1]); /*Si falta el argumento n (argc != 2), terminamos el proceso y devolvemos un 1 (falló execución). De otro modo convertimos la cadena de caracteres de la linea de comando a un entero utilizando la rutina predefinida atoi.*/
29
Código (cont) low_value = 2 + BLOCK_LOW(id,p,n-1); high_value = 2 + BLOCKHIGH(id,p,n-1); size = BLOCK_SIZE(id,p,n-1); /* Hacen uso de los macros guardados en MyMPI.h para determinar el primero y ultimo números y el tamaño del bloque */ proc0_size = (n-1)/p; if ((2 + proc0_size) * (2+proc0_size) < n ){ if (!id) printf ("Too many processes\n"); MPI_Finalize(); exit (1); }// Verificar que el Próximo Valor de k siempre esté en el Proceso 0
30
Código (cont) marked = (char *) malloc (size);/* Cada elemento del arreglo marked consistirá de un byte*/ if (marked == NULL) { printf ("Cannot allocate enough memory\n"); MPI_Finalize(); exit (1); }//Assign memory for data in each proc for (i=0; i<size; i++) marked[i]=0; /* Inicialmente ningún número está marcado*/ /* prime juega del papel de k y index es su indice */ if(!id) index = 0; /*El proceso 0 es el único proceso que necesita el valor de esta variable*/ prime = 2;
31
Código (cont) do { //Marcar los no primos if (prime * prime > low_value) first = prime * prime - low_value;//la posicion de prime 2 else { if (!(low_value % prime)) first = 0;//primer elemento del bloque es //un multiplo de prime else first = prime - (low_value % prime);//posición del primer //multiplo de un multiplo de prime. } for (i = first; i < size; i += prime) marked[i] = 1;//marcar todos los multiplos //de prime en el bloque if (!id) { while (marked[++index]);//buscar próxima posición no marcada prime = index + 2; // el primo que corresponde a esta posición } MPI_Bcast (&prime, 1, MPI_INT, 0, MPI_COMM_WORLD); //enviar nuevo //valor de prime a los otros procesos } while (prime * prime <= n);
32
Contar el Número de Primos count = 0; //Count the primes found by this processor for (i = 0; i < size; i++) if (!marked[i]) count++; MPI_Reduce (&count, &global_count,1,MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); //Find the total number of primes if (!id) printf ("%d primes are less than or equal to %d\n", global_count, n); MPI_Finalize (); return 0; }
33
Mejorar el Rendimiento Eliminar los números pares Esto reduce por la mitad el número de computaciones y reduce la cantidad de almacenaje
34
Eliminar Broadcast Hacer el programa de tal forma que todo proceso identifique el próximo valor de k. Esto se puede hacer si todo proceso tiene su propio arreglo que contiene los enteros 3,5,7,…, n y que luego compute secuencialmente la lista de primos entre 3 y n
35
Asignación (véase Sección 5.9 del texto) Escribir un programa que cuenta el número de primos ≤ n haciendo los siguientes dos cambios al programa que estudiamos en clase: (a) Considerar solamente los impares ≤ n (b) Eliminar broadcast Para entregar no mas tarde que el martes, 10 de mayo.
36
Reorganizar los Bucles El bucle exterior itera sobre primos entre 3 y n y el bucle interior itera sobre un arreglo que representa la porción de datos de un proceso. La razón de “cache misses” puede ser grande debido a la disperción grande de los primos. Esto se puede mejorar intercambiando los bucles.
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.