ALGORITMOS Y PROGRAMACIÓN PARALELA Esquemas de programación paralela REFERENCIAS • Almeida, Giménez, Mantas, Vidal: Introducción a la Programación Paralela. Cap 5 y 6 • Wilkinson, Allen • Quinn Programación Paralela Esquemas de Programación Paralela 1 Esquemas de algoritmos paralelos * Paralelismo de datos * Particionado de datos * Algoritmos relajados * Recorrido de un árbol * Computación pipeline * Paralelismo síncrono * Divide y vencerás * Programación dinámica * Branch and Bound * Trabajadores replicados Programación Paralela Esquemas de Programación Paralela 2 Paralelismo de datos * Muchos datos tratados de una forma igual o similar (apropiado para GPU) * Algoritmos numéricos * Datos en arrays o vectores - Procesamiento vectorial - Paralelismo asignando partes distintas del array a distintos procesadores * Memoria Compartida: - Distribución del trabajo - Paralelización automática * Memoria Distribuida: - Distribución de los datos - Técnica de particionado de datos Programación Paralela Esquemas de Programación Paralela 3 Paralelismo de datos Ejemplo: suma de n datos * Esquema: s=0 for i=0 to n-1 s=s+a[i] endfor * Paralelización automática: Con opción de compilación si no hay dependencia de datos * Con pragma: s=0 #Pragma: for paralelo (a compartida de lectura, s compartida de lectura-escritura) #pragma omp parallel for for i=0 to n-1 private(i) reduction(+:s) s=s+a[i] endfor * Distintas posibilidades de asignación de los datos a los procesadores: - Bloques contiguos scheduling(static,tamano) - Cíclico - Incremental Programación Paralela Esquemas de Programación Paralela 4 Paralelismo de datos Ejemplo: suma de n datos * Con paralelismo explícito: #Pragma: llamada concurrente (i=0 to p-1) sumaparcial( &a[(i*n)/p] , i ) if nodo=0 s=sumatotal() endif sumatotal(): sumaparcial( a , i ): s=0 s=0 for j=0 to p-1 step n/p for j=0 to n/p-1 s=s+a[j] s=s+a[j] endfor endfor return s a[0]=s *¿Paralelización de sumatotal? Si pocos procesadores suele ser preferible que lo haga uno solo Programación Paralela Esquemas de Programación Paralela 5 Paralelismo de datos Ejemplo: ordenación por rango * Paralelismo implícito: #Pragma: for paralelo (a compartida de lectura, r compartida de lectura-escritura) for i=0 to n-1 for j=0 to n-1 if a[i]>a[j] r[i]=r[i]+1 endif endfor endfor se asignan varios valores de i a cada procesador no hay problemas de coherencia en r Programación Paralela Esquemas de Programación Paralela 6 Paralelismo de datos Ejemplo: ordenación por rango * Paralelismo explícito: #Pragma: llamada concurrente (for i=0 to p-1) calcularrango(a,i) calcularrango(a,i): for j=(i*n)/p to ((i+1)*n)/p-1 for k=0 to n-1 if a[j]>a[k] r[j]=r[j]+1 endif a endfor r endfor P0 P1 P2 n n n n/p n/p n/p se hace asignación del trabajo entre los procesadores Programación Paralela Esquemas de Programación Paralela 7 Paralelismo de datos Ejemplo: multiplicación de matrices * Paralelismo implícito: #Pragma: for paralelo (a,b compartida de lectura, c compartida de lectura-escritura) for i=0 to n-1 for j=0 to n-1 C A B c[i,j]=0 P0 P0 P0 for k=0 to n-1 c[i,j]=c[i,j]+a[i,k]*b[k,j] P1 = P1 P1 endfor P2 P2 P2 endfor endfor Posiblemente mejor usar bloques contiguos para mejor uso de la caché Programación Paralela Esquemas de Programación Paralela 8 Paralelismo de datos Ejemplo: multiplicación de matrices * Paralelismo explícito: #Pragma: llamada concurrente (for i=0 to p-1) multiplicar(c,a,b,i) multiplicar(c,a,b,i): for j=(i*n)/p to ((i+1)*n)/p-1 for k=0 to n-1 c[j,k]=0 for l=0 to n-1 c[j,k]=c[j,k]+a[j,l]*b[l,k] endfor endfor endfor Programación Paralela Esquemas de Programación Paralela 9 Particionado de datos * Especie de paralelismo de datos en Multicomputadores (Memoria Distribuida) * El espacio de datos se divide en regiones adyacentes: - Se asignan a procesadores distintos - Intercambio de datos entre regiones adyacentes * Para obtener buenas prestaciones: intentar que el volumen de computación entre comunicaciones sea grande (paralelismo de grano grueso) Programación Paralela Esquemas de Programación Paralela 10 Particionado de datos Ejemplo: suma de n datos - Computación: suma de n/p datos en cada procesador. - Comunicación: envío de datos (si no están distribuidos) igual conste que la computación acumulación de los resultados depende de la topología se puede pensar en topología lógica - El programa similar al de Memoria Compartida. n P0 P1 P2 Programación Paralela Esquemas de Programación Paralela 11 Particionado de datos Ejemplo: ordenación por rango • En paralelismo de datos se distribuía el trabajo: a P0 P1 P2 r P0 P1 P2 en particionado de datos puede ser: P0 P1 a a r0 r1 P2 a r2 • Podría ser que los datos estuvieran inicialmente de otra manera: a0 r0 P0 a1 r1 P1 a2 r2 P2 Pi se encarga de calcular los valores de ri, necesita comparar ai con cada aj ⇒ p pasos Programación Paralela Esquemas de Programación Paralela 12 Particionado de datos Ejemplo: ordenación por rango En cada Pi, i=0,1,...,p-1 for j=0 to n/p-1 b[j]=a[j] endfor for j=1 to p for k=0 to n/p-1 for l=0 to n/p-1 if a[k]>b[l] r[k]=r[k]+1 endif endfor endfor enviar a[0]...a[n/p-1] a P(i-1) mod p recibir en b[0],...,b[n/p-1] de P(i+1) mod p endfor Programación Paralela Esquemas de Programación Paralela 13 Algoritmos relajados * Cada procesador computa de manera independiente. - No hay sincronización ni comunicación. * Buenas prestaciones en Memoria Compartida y Distribuida. - A veces a costa de no utilizar el mejor algoritmo paralelo. * Fáciles de programar. * Difícil encontrar algoritmos que se adecúen a este esquema. Programación Paralela Esquemas de Programación Paralela 14 Algoritmos relajados Ejemplo: raíces de una función Dividir el espacio de búsqueda en p subespacios: p0 p1 p2 p3 - Puede haber desbalanceo. - La programación es muy sencilla. Programación Paralela Esquemas de Programación Paralela 15 Algoritmos relajados Ejemplo: ordenación por rango - Memoria Compartida: cada procesador calcula el rango de una parte de los elementos. - Memoria Distribuida: si la distribución es a b r p0 p0 p0 p1 p1 p1 p2 p2 p2 duplicación de datos simplifica la programación buenas prestaciones Programación Paralela Esquemas de Programación Paralela 16 Algoritmos relajados Ejemplo: multiplicación de matrices * En Memoria Compartida: cada procesador calcula un bloque de filas de la matriz resultado. * En Memoria Distribuida con: A p0 C p0 p1 p2 = B p1 p0 p1 p2 p2 Cada procesador calcula las filas de C correspondientes a las filas de A que contiene. No es necesaria sincronización ni comunicación. - Pero: más costoso el envío inicial al repetirse B en cada procesador. Programación Paralela Esquemas de Programación Paralela 17 Recorrido de árboles y grafos * Muchos problemas tienen una representación (física o lógica) en forma de árbol o grafo con raíz, y su resolución consiste en recorrer el árbol o grafo hasta la raíz realizando computaciones. Para resolverlo en paralelo: - Asignar el trabajo de diferentes nodos a distintos procesadores. - Los arcos representan precedencias en la computación, e implican en algunos casos comunicaciones. x entrada de datos xx bx * Grafos de precedencia: precedencia axx bx+ c cominucación axx+bx +c salida de datos p0 p1 Ej: evaluar ax2+bx+c Programación Paralela Esquemas de Programación Paralela 18 Recorrido de árboles y grafos * La suma de n números la realizamos con un árbol binario: p0 p1 p2 p3 * Suma prefija: dada una secuencia {x0,x1,...,xn-1} formar si=x0+x1+...+xi, con i=0,1,...,n-1 0 1 2 3 4 5 6 7 0 1 1 2 0 2 2 3 0 3 3 4 1 4 0 4 5 2 5 0 5 6 3 6 0 6 7 4 7 0 Programación Paralela Esquemas de Programación Paralela 19 Recorrido de árboles y grafos Ejemplo: suma prefija Para cada Pi, i=0,1,...,n-1 desp=1 for j=0 to log n-1 if i<(n-desp) enviar x a Pi+desp endif if i>=desp recibir en y de Pi-desp x=x+y endif desp=desp*2 endfor Programación Paralela Esquemas de Programación Paralela 20 Recorrido de árboles y grafos Ejemplo: clases de equivalencia En una representación de conjuntos por medio de árboles: 2 1 3 5 7 8 4 6 9 se trata de encontrar el representante de la clase a la que pertenece cada nodo. Los arcos indican comunicaciones si están en distinto procesador. De cada nodo sale como mucho un arco ⇒ el patrón de comunicaciones es fijo. Para cada nodo se lee el valor del padre, si el valor leído es igual al que hay en el nodo ese nodo envía un mensaje de fin al nodo con el que se comunica y acaba. 1 ← 2 ← 3 4 ← 5 6 ← 7 → 8 → 9 2 3 3 5 5 7 7 7 8 3 3 3 5 5 7 7 7 Programación Paralela Esquemas de Programación Paralela 7 21 Computación pipeline * Resolver un problema descomponiéndolo en una serie de tareas sucesivas: p0 p1 p2 los datos fluyen por la estructura de los procesadores. * El coste será mayor que el de la tarea más costosa. Puede tener interés cuando: - no hay un único conjunto de datos a tratar sino una serie de conjuntos de datos. - no se necesite que una tarea esté completamente finalizada para empezar la siguiente. * Cada tarea puede tener un peso diferente y ser preferible dedicar distinto número de procesadores a cada tarea: p 0 p 1 p 3 p 5 p 2 p 4 p 6 * Tiene estructura lógica de Multicomputador. Programación Paralela Esquemas de Programación Paralela 22 Computación pipeline Ejemplo: sistema triangular inferior de ecuaciones lineales a a 00 0 10 a x x + 0 ... n −1,0 x 0 + a 11 a = = x 1 ... n −1,n −1 x 1 ... + ... b b 0 1 ... + a n −1,n −1 x n −1 = b n −1 Sustitución progresiva: considerando un procesador por fila, pi calcula xi. x b i i = − i −1 ∑a x j =0 a ij j jj Programación Paralela Esquemas de Programación Paralela 23 Computación pipeline Ejemplo: sistema triangular inferior de ecuaciones lineales #Pragma: llamada concurrente (for i=0 to n-1) resolver(i) resolver(i): suma=0 for j=0 to i-1 P(valor[j]) V(valor[j]) suma=suma+a[i,j]*x[j] endfor x[i]=(b[i]-suma)/a[i,i] V(valor[i]) donde: - valor[i] son semáforos inicializados a 0. - se puede hacer con otras construcciones como llaves o canales. Programación Paralela Esquemas de Programación Paralela 24 Computación pipeline Ejemplo: sistema triangular inferior de ecuaciones lineales - Coste secuencial: - Coste paralelo: - Speed-up: - Eficiencia: n 8 2 n + n 8 n 12.5% * Con procesos de mayor grano: n/p filas por procesador eficiencia del 50%, porque se puede empezar la computación de una tarea sin haberse acabado la de las anteriores. Programación Paralela Esquemas de Programación Paralela 25 Computación pipeline Ejemplo: sistema triangular inferior de ecuaciones lineales * En Memoria Distribuida, sustituir los semáforos por envíos y recepciones: En cada Pi, i=0,1,...,n-1 if i=0 x=b/a[0] enviar x a P1 else if i<>n-1 for j=0 to i-1 recibir x de Pi-1 enviar x a Pi+1 suma=suma+a[j]*x endfor x=(b-suma)/a[i] else for j=0 to n-2 recibir x de Pn-2 suma=suma+a[j]*x endfor x=(b-suma)/a[n-1] endif Programación Paralela Esquemas de Programación Paralela 26 Divide y vencerás * Idea general: Dividir un problema p en subproblemas p1,p2,...pn Resolver los subproblemas pi obteniendo si Combinar las soluciones parciales s1,s2,...,sn para obtener la solución global de p El éxito del método depende de que se pueda hacer la división y la combinación de forma eficiente. * Paralelismo: La solución de los subproblemas se puede hacer en paralelo ⇒ la división debe producir subproblemas de coste balanceado la división y la combinación implicarán comunicaciones y sincronización Es el esquema más adecuado para paralelizar, se puede considerar que todos los programas paralelos siguen este esquema. Programación Paralela Esquemas de Programación Paralela 27 Divide y vencerás Ejemplo: ordenación por mezcla * Multiprocesador: #Pragma: llamada concurrente (for i=0 to p-1) ordenarsimple(i,a) (*Ordenar en cada procesador el trozo de array que le corresponde*) proc=p/2 (*Número de procesadores que intervienen en la mezcla*) * Secuencial, recursivo: for j=1 to log p-1 ordenar(p,q,a): #Pragma: llamada concurrente (for i=0 to proc-1) if q-p>lim mezclar(i,n/proc,a) m=(p+q)/2 proc=proc/2 ordenar(p,m,a) endfor ordenar(m+1,q,a) mezclasimple(0,n,a) mezclar(p,m,q,a) else mezclar(i,l,a): ordenarbasico mezclasimple(i*l,(i+1)*l-1,a) endif No hay recursión: se divide en función Programación Paralela Esquemas de Programación Paralela 28 del número de procesadores. Divide y vencerás Ejemplo: ordenación por mezcla * Multicomputador: Se hace una acumulación de los Enviar n/p datos a cada procesador tramos ordenados sobre cada En cada Pi, i=0,1,...,p-1 procesador en el procesador 0, ordenar(0,n/p-1,a) haciendo mezclas conforme se va p0 p1 p2 p3 activo=1 acumulando: desp=2 for j=1 to log p if activo=1 if i mod desp=0 recibir en b (n/p)*(desp/2) datos de Pi+desp/2 mezclar a y b en a else enviar (n/p)*(desp/2) datos de a a Pi-desp/2 activo=0 endif desp=desp*2 Programación Paralela endif Esquemas de Programación Paralela 29 Divide y vencerás Ejemplo: ordenación rápida * Secuencial: ordenar(p,q,a): * Multiprocesador: if q-p>lim m[0]=0 m=particionar(p,q,a) m[1..p]←n-1 ordenar(p,m,a) m[p/2]=particionar(0,n-1,a) ordenar(m+1,q,a) proc=2 else ordenarbasico for j=1 to log p-1 endif #Pragma: llamada concurrente En el particionado se hace la ordenación (for i=0 to proc-1) m[p/(2*proc)+i*p/proc]=particionar(m[i*p/proc],m[(i+1)*p/proc],a) proc=2*proc endfor #Pragma: llamada concurrente (for i=0 to p-1) ordenar(m[i],m[i+1],a) Al particionar se forman grupos de datos ordenados entre sí, utilizando el array m de índices para indicar los límites de las particiones. El trabajo no estará balanceado porque las secuencias de datos no Programación Paralela tienen la misma longitud. Esquemas de Programación Paralela 30 Divide y vencerás Ejemplo: ordenación rápida * Multicomputador: Suponiendo que tenemos los datos en En cada Pi, i=0,1,...,p-1 el procesador 0 se irán haciendo y m1=n-1 ; desp=p ; activo=0 enviando particiones, de manera que if i mod (desp/2)=0 activo=1 endif en cada paso se duplica el número de for j=1 to log p procesadores implicados. if activo=1 if i mod desp=0 m=particionar(0,m1,a) enviar m1-m+1 y a[m+1],...,a[m1] a Pi+desp/2 m1=m else recibir en l y a de Pi-desp/2 m1=l-1 m=particionar(0,m1,a) enviar m1-m+1 y a[m+1],...,a[m1] a Pi+desp/2 m1=m Hay desbalanceo y mensajes de distinta endif longitud. endif desp=desp/2 if i mod (desp/2)=0 activo=1 endif endfor Programación Paralela ordenar(a) y acumular sobre P0 Esquemas de Programación Paralela 31 Programación dinámica * Para resolver problemas de optimización. Obteniendo soluciones de subproblemas de menor a mayor tamaño hasta llegar al tamaño deseado. Las soluciones parciales se pueden guardar en un array construyendo el array de la primera fila hasta la última, usándose para cada fila los valores de las anteriores: problema a resolve Programación Paralela Esquemas de Programación Paralela 32 Programación dinámica * En Memoria Compartida: En cada fila intervienen los procesadores obteniendo cada uno valores de distintos tamaños, basándose en la línea anterior para leer ⇒ no hay problema de coherencia, pero se necesita sincronización entre los pasos sucesivos (uno por línea). * En Memoria Distribuida: Un procesador puede necesitar datos almacenados en otro: indicados por las flechas que cruzan la línea gruesa. Programación Paralela Esquemas de Programación Paralela 33 Programación dinámica Ejemplo: problema de la mochila 0/1 Mochila de capacidad C objetos numerados 1,2,...,n cada objeto tiene un peso pi y un beneficio bi. n ∑ Maximizar i =1 xi bi n pi ≤ C x i sujeto a xi=0 o 1, y ∑ i =1 Se obtiene la fórmula: M (i , X ) =max{M (i −1, X ), M (i −1, X − pi ) +bi} Ejemplo: 9 1 4 2 C=9 p=(3,5,2) b=(4,6,5) 1 2 3 4 5 6 7 8 0 0 4 4 4 4 4 0 0 Programación Paralela 4Esquemas 4de Programación 6 Paralela 6 4 6 34 Programación dinámica Ejemplo: problema de la mochila 0/1 * Multiprocesador: for i=1 to n-1 #Pragma: llamada concurrente (for j=1 to p) calcular(i,j,M) endfor M[n,C]=max{M[n-1,C],M[n-1,C-p[n]]+b[n]} calcular(i,j,M): for k=(j-1)*C/p+1 to j*C/p M[i,k]=max{M[i-1,k],M[i-1,k-p[i]]+b[i]} endfor Programación Paralela Esquemas de Programación Paralela 35 Programación dinámica Ejemplo: problema de la mochila 0/1 * Multicomputador: Suponemos una columna por procesador. Para cada Pi, i=1,...,C if p[1]≤i M=b[1] (*Se rellena la primera fila*) else M=0 endif if i+p[2]≤C (*Se comprueba qué procesadores necesitan datos*) enviar M a Pi+p[2] endif for j=2 to n-1 if i-p[j]≥1 (*Se comprueba si recibe dato de la fila anterior*) recibir en N de Pi-p[j] else N=0 endif M=max{M,N+b[j]} if i+p[j+1]≤C enviar M a Pi+p[j+1] endif endfor if i-p[n]≥1 recibir en N de Pi-p[n] else N=0 endif M=max{M,N+b[j]} Programación Paralela Esquemas de Programación Paralela 36 Paralelismo síncrono * Iteraciones sucesivas: - cada procesador realiza el mismo trabajo sobre una porción distinta de los datos. - datos de una iteración se utilizan en la siguiente. - al final de cada iteración sincronización (local o global). * Prestaciones afectadas por la sincronización: - en Memoria Compartida buenas prestaciones. - en Memoria Distribuida bajan las prestaciones pues hay comunicación. Programación Paralela Esquemas de Programación Paralela 37 Paralelismo síncrono Ejemplo: solución de ecuación diferencial . . . . . Relajación de Jacobi para . . . . . resolver una ecuación de Laplace: . . . . . δ v + δ v =0 . . . . . δ x δ y . . . . . Ecuación de diferencias: 2 2 2 V (i , j ) = valores fijos en la frontera 2 V ( i − 1, j ) + V ( i + 1, j ) + V ( i , j − 1) + V ( i , j + 1) 4 - Converge gradualmente a una solución cada vez más precisa. - Para obtener una solución más precisa aumentar el número de puntos del array. - Una iteración tras otra secuencialmente, pero dentro de cada iteración paralelismo. Programación Paralela Esquemas de Programación Paralela 38 Paralelismo síncrono Ejemplo: solución de ecuación diferencial * En Multiprocesador: b←a for i=1 to numiter/2 #Pragma: for paralelo (a compartida de lectura, b compartida de escritura) for j=1 to n for k=1 to n b[j,k]=(a[j-1,k]+a[j+1,k]+a[j,k-1]+a[j,k+1])/4 endfor endfor #Pragma: for paralelo (a compartida de escritura, b compartida de lectura) (*lo mismo del pragma anterior pero de b en a*) endfor - Sincronización por acabar el pragma. - En dos partes para evitar copias. - Asigna filas completas a cada procesador: Programación Paralela topología lógica de anillo. Esquemas de Programación Paralela 39 Paralelismo síncrono Ejemplo: solución de ecuación diferencial * Puede ser más interesante crear un proceso por cada procesador: b←a #Pragma: llamada concurrente (for i=0 to p-1) iterar(a,b,i) iterar(a,b,i): for j=1 to numiter/2 for k=i*n/p+1 to (i+1)*n/p for l=1 to n b[k,l]=(a[k-1,l]+a[k+1,l]+a[k,l1]+a[k,l+1])/4 endfor endfor En Memoria Distribuida a y b son BARRERA locales: (*lo mismo pero de b en a*) La barrera implica sincronización y BARRERA comunicación. endfor Programación Paralela Esquemas de Programación Paralela 40 Paralelismo síncrono Barrera lineal * Normalmente las barreras se proporcionan con el sistema. * Se pueden implementar de distintas maneras. * Implementación por conteo de variables: Barrera: P(llegada) cont=cont+1 if cont<n V(llegada) else Coste lineal. V(salida) endif En Memoria Distribuida habría que P(salida) acceder a una variable global. cont=cont-1 if cont>0 V(salida) else V(llegada) Programación Paralela endif Esquemas de Programación Paralela 41 Paralelismo síncrono Barrera en árbol * La contención se puede reducir descentralizando: Sincronización por subgrupos y después centralizar. Ej: suma de números, donde se acumulan los resultados parciales para obtener el total. * Barrera en árbol: 0 1 2 3 Programación Paralela Esquemas de Programación Paralela 42 Paralelismo síncrono Barrera en árbol barrera(i): (*i=0,...,p-1; número de proceso*) des=1 des=p act=1 for j=1 to log p for j=1 to log p des=des/2 if act=1 if i mod des=0 des=des*2 act=1 endif if i mod des>0 if act=1 activo=0 if i mod (des*2)=0 enviar a Pi-des/2 else enviar a Pi+des recibir de Pi+des/2 else endif recibir de Pi-des endif endif endfor endif endfor Coste log p, pero más complejo que el lineal. Programación Paralela Esquemas de Programación Paralela 43 Paralelismo síncrono Ejemplo: relajación de Jacobi. Sincronización local * El paso de una iteración a la siguiente puede no necesitar de sincronización global: A B para calcular b[i,:] basta con conocer a[i-1,:], a[i,:], a[i+1,:] barreralocal(i): if i>1 superior[i-1]=1 endif if i<n inferior[i+1]=1 basura=superior[i] superior e inferior son “canales” de 0 a n+1 endif if i>1 basura=inferior[i] endif Programación Paralela Esquemas de Programación Paralela 44 Paralelismo síncrono Ejemplo: relajación de Jacobi. Sincronización local * En Memoria Distribuida: Además habría que enviar y recibir barreralocal(i): datos. if i>0 enviar a Pi-1 - Coste de las transferencias 4α+4nβ endif - Si se asignan bloques cuadrados if i<p-1 enviar a Pi+1 n 8α + 8 β endif p if i>0 ⇒ más escalable recibir de Pi-1 endif if i<p-1 recibir de Pi+1 endif Programación Paralela Esquemas de Programación Paralela 45 Paralelismo síncrono Ejemplo: relajación de Jacobi. * Comparación de las distintas técnicas de sincronización: 12 10 8 local 6 árbol lineal 4 2 0 1 2 3 4 5 6 7 8 9 10 * Test de convergencia: - El número de iteraciones puede no ser fijo, puede depender de la norma ||a-b|| ⇒ calcular la norma distribuida, acumular y difundir el resultado. - No es costoso en comparación con el coste total. Programación Paralela Esquemas de Programación Paralela 46 Branch and Bound * En problemas de búsqueda en un espacio de soluciones. El espacio de búsqueda es un árbol donde cada nodo representa un subespacio de búsqueda. Obtener solución óptima explorando la menor cantidad posible de nodos. * Características: - expansión: el trabajo en un nodo consiste en generar todos los hijos obteniendo por cada nodo unas cotas inferior y superior del beneficio alcanzable por una solución a partir de ese nodo, y una estimación del beneficio obtenible. - selección: de todos los nodos vivos (de los que no se han generado los hijos) se elige uno según algún criterio: primero generado, el de mayor beneficio estimado, ... - poda: para evitar generar nodos innecesarios, cuando la cota inferior de un nodo es mayor que la cota superior de otro, éste último se puede eliminar * Es proceso secuencial: se necesita información global para la selección Programación Paralela y la poda. Esquemas de Programación Paralela 47 Branch and Bound Posibilidades de paralelismo * Búsqueda paralela usando diferentes algoritmos en diferentes procesadores: diferencias en el cálculo de las cotas, de la estimación del beneficio, y del criterio de selección. -Se repiten nodos pero hay pocas comunicaciones. * Expansión en paralelo de cada nodo: - Se necesita que la expansión de cada nodo sea costosa: gran número de hijos, alto coste de los cálculos de cada hijo. - Gestión de la lista de nodos vivos centralizada ⇒ muchas comunicaciones. Programación Paralela Esquemas de Programación Paralela 48 Branch and Bound Posibilidades de paralelismo * Evaluación paralela de subproblemas: - De la lista de nodos vivos se asignan diferentes nodos a cada procesador. - Posibilidades en la distribución de los nodos: 1. Estática: pocas comunicaciones, se pueden difundir las cotas para podar. con asignación balanceada de nodos, con asignación ponderada de nodos. 2. Asignación dinámica con bolsa de tareas: más comunicaciones. con actualización inmediata de la bolsa de tareas, con actualización pospuesta. Programación Paralela Esquemas de Programación Paralela 49 Branch and Bound Ejemplo * Secuencial: 2 -7 -1 0 1 2 -6 -9 4 -6 -8 5 3 -8 -1 0 5 -6 -8 6 5 3 -6 -9 7 6 2 4 -8 -1 0 6 7 8 9 10 6 p1 3 5 8 4 9 11 6 7 1 2 7 5 * Paralelo comunicando cotas: 1 4 4 8 * Paralelo sin comunicar cotas: p0 3 8 p0 4 5 9 6 2 7 6 5 7 p1 3 4 8 Programación Paralela Esquemas de Programación Paralela 5 9 6 50 7 Trabajadores replicados * Se mantiene una bolsa central de tareas. * Trabajadores: - Toman tareas de la bolsa. - Generan otras nuevas. * Acaba la computación cuando la bolsa está vacía y todos los trabajadores han acabado. * Útil en problemas combinatorios: búsqueda en árbol. * Asignación dinámica de trabajos para balancear la computación. Programación Paralela Esquemas de Programación Paralela 51 Trabajadores replicados * Bolsa de tareas: conjunto de descriptores de tareas, cada descriptor especifica una computación. * En Multiprocesadores: una estructura centralizada de la que los trabajadores toman trabajos y posiblemente depositan otros nuevos * En Multicomputadores: la estructura en la memoria de uno o varios procesadores, petición y depósito de tareas conllevan comunicación. * Aspectos a tener en cuenta: - Contención: Por ser la bolsa de tareas centralizada. Cuantos más procesadores mayor contención. - Balanceo: Si se descentraliza la bolsa: mayor desbalanceo y menor contención ⇒ compromiso entre contención y balanceo - Terminación: El test de terminación es global ⇒ sincronización. Programación Paralela Esquemas de Programación Paralela 52 Trabajadores replicados Ejemplo: algoritmo del camino más corto En un grafo dirigido, encontrar el camino más corto de un vértice a los demás. Estructuras: vertices: 1..n distancia←∞ pesos: array[1..n,1..n] cola={1} distancia: array[1..n] distancia[1]=0 while no vacía cola cola: conjunto de vértices para los x=el de menor distancia en la cola que se ha actualizado la for i=1 to n distancia mínima. dist=distancia[x]+pesos[x,i] if dist<distancia[i] distancia[i]=dist if i no está en la cola incluir i en la cola endif endif endfor endwhile Programación Paralela Esquemas de Programación Paralela 53 Trabajadores replicados Ejemplo: algoritmo del camino más corto Ejemplo: 1 2 3 4 5 1 ∞ 4 8 ∞ ∞ 2 ∞ ∞ 3 1 ∞ 3 ∞ ∞ ∞ ∞ 5 4 ∞ ∞ 2 ∞ 10 5 ∞ ∞ ∞ ∞ inicialmente: paso1: paso2: paso3: paso4: paso5: cola=1 cola=2,3 cola=4,3 cola=3,5 cola=5 cola=∅ ∞ distancias: 0,∞,∞,∞,∞ distancias: 0,4,8,∞,∞ distancias: 0,4,7,5,∞ distancias: 0,4,7,5,15 distancias: 0,4,7,5,12 distancias: 0,4,7,5,12 Programación Paralela Esquemas de Programación Paralela 54 Trabajadores replicados Ejemplo: algoritmo del camino más corto. Memoria Compartida Programa: distancia←∞ if dist<distancia[j] enconjunto←false distancia[j]=dist distancia[1]=0 desbloquear distancia[j] enconjunto[1]=true bloquear enconjunto[j] #Pragma: llamada concurrente (for i=1 to p) if not enconjunto[j] trabajador(i) enconjunto[j]=true desbloquear enconjunto[j] trabajador(i): poner(i,j) tomar(i,v) else while v<>-1 (*-1 indica que ha acabado*) desbloquear enconjunto[j] bloquear enconjunto[v] endif enconjunto[v]=false else desbloquear enconjunto[v] desbloquear distancia[j] for j=1 to n endif if pesos[v,j]<∞ endif bloquear distancia[v] endfor dist=distancia[v]+pesos[v,j] endwhile desbloquear distancia[v] bloquear distancia[j] Programación Paralela Esquemas de Programación Paralela 55 Trabajadores replicados Ejemplo: algoritmo del camino más corto. Memoria Compartida Contadores: trabajadores=p tareas=1 (*trabajadores activos*) (*tareas por hacer*) tomar(i,j): bloquear trabajadores cont=trabajadores-1 trabajadores=cont poner(i,j): desbloquear trabajadores bloquear tareas if cont=0 tareas=tareas+1 bloquear tareas desbloquear tareas if tareas=0 desbloquear tareas bloquear cola j=-1 insertar j en cola else desbloquear cola desbloquear tareas bloquear cola j=cabeza de cola El bloqueo con espera activa desbloquear cola endif else bloquear cola j=cabeza de cola desbloquear cola Programación Paralela endif Esquemas de Programación Paralela 56