Problemas de aula resueltos

Teoría: Tema 1 - Evaluación de las prestaciones · Tema 2 - Diseño de algoritmos paralelos · Exámenes: Problemas de examen resueltos


Receta para cualquier problema de prestaciones

  1. T(n)T(n) secuencial: contar FLOPs × tct_c.
  2. T(n,p)T(n,p): lo que tarda el procesador más cargado: su cálculo + sus comunicaciones. Cada mensaje cuesta ts+(taman˜o) twt_s + (\text{tamaño})\,t_w; un envío y una recepción cuentan como dos mensajes (en el curso se suman, no se solapan).
  3. Coste: C=p T(n,p)C = p\,T(n,p).
  4. Sobrecarga: T0=C−T(n)T_0 = C - T(n). El término de cálculo se cancela si el reparto es perfecto: lo que queda en T0T_0 es lo que "sobra" (comunicaciones, desequilibrio, cálculo redundante).
  5. Speedup y eficiencia: S=T(n)/T(n,p)S = T(n)/T(n,p),   E=S/p\;E = S/p. Truco: dividir numerador y denominador para dejar E=11+T0/T(n)E = \dfrac{1}{1 + T_0/T(n)}.
  6. Escalabilidad (isoeficiencia): W∝K T0W \propto K\,T_0, término a término (tct_c, tst_s, twt_w). Para cada uno despejar WW en función de pp:
    • Si sale W∈θ(p)W \in \theta(p): óptima. θ(plog⁡p)\theta(p\log p): buena. θ(p2)\theta(p^2) o peor: pobre.
    • Si nn aparece igual en los dos lados y se cancela (1∝Kp1 \propto Kp): no escala.
    • Si el término no depende de pp: no afecta.
  7. Ojo con las restricciones entre nn y pp (p. ej. p=np = n o p=n2p = n^2): aunque T0T_0 sea 0, si pp no puede pasar de nn, el problema tiene que crecer como W≥p2W \ge p^2 para usar más procesadores.

Evaluación de las prestaciones

Todos los problemas usan el mismo dominio: una matriz n×nn \times n, 1 FLOP por elemento, y cada elemento depende solo de sus vecinos de arriba y de abajo (la figura del enunciado es una malla con aristas solo verticales). Por tanto:

T(n)=n2tcT(n) = n^2 t_c

Problema 1: una tarea por elemento (p=n2p = n^2)

Cada procesador actualiza un elemento (1 FLOP) e intercambia su valor con el vecino de arriba y el de abajo: 2 envíos + 2 recepciones = 4 mensajes de 1 dato.

T(n,p)=tc+4(ts+tw)T(n,p) = t_c + 4(t_s + t_w)
C(n,p)=p tc+4p(ts+tw)T0(n,p)=p tc−n2tc⏟=0 porque p=n2+4p(ts+tw)=4p(ts+tw)C(n,p) = p\,t_c + 4p(t_s + t_w) \qquad T_0(n,p) = \underbrace{p\,t_c - n^2 t_c}_{=0 \text{ porque } p = n^2} + 4p(t_s + t_w) = 4p(t_s + t_w)
S(n,p)=n2tctc+4(ts+tw)E(n,p)=n2tcn2(tc+4(ts+tw))=tctc+4(ts+tw)S(n,p) = \frac{n^2 t_c}{t_c + 4(t_s + t_w)} \qquad E(n,p) = \frac{n^2 t_c}{n^2\big(t_c + 4(t_s+t_w)\big)} = \frac{t_c}{t_c + 4(t_s + t_w)}

Interpretación:

  • T0T_0 no tiene término en tct_c: el cálculo está perfectamente repartido.
  • La eficiencia no depende ni de nn ni de pp: es constante, así que el algoritmo es escalable sin hacer más cálculos (en isoeficiencia: W∝KW⇒1∝KW \propto KW \Rightarrow 1 \propto K, no depende de pp). El tiempo paralelo también es constante.
  • Pero la eficiencia es malísima: con ts=10−5t_s = 10^{-5}, tw=10−6t_w = 10^{-6}, tc=10−7t_c = 10^{-7} sale E=10−74.41⋅10−5≈2.27⋅10−3E = \frac{10^{-7}}{4.41 \cdot 10^{-5}} \approx 2.27 \cdot 10^{-3} y T(n,p)=4.41⋅10−5T(n,p) = 4.41 \cdot 10^{-5} s. Cada tarea hace 1 FLOP y 4 mensajes: la granularidad es demasiado fina. Hay que agrupar.

Problema 2: agrupar por filas y por columnas (p=np = n)

Por filas. Cada procesador tiene una fila completa (nn elementos). Las dependencias son verticales, así que necesita la fila de arriba y la de abajo: 4 mensajes de nn datos.

T(n,p)=n tc+4(ts+n tw)T(n,p) = n\,t_c + 4(t_s + n\,t_w)
C=p n tc+4p(ts+n tw)T0=4p(ts+n tw)C = p\,n\,t_c + 4p(t_s + n\,t_w) \qquad T_0 = 4p(t_s + n\,t_w)
E=11+4p(ts+ntw)n2tc=p=n11+4(ts+ntw)n tc  →  n→∞    11+4twtcE = \frac{1}{1 + \dfrac{4p(t_s + n t_w)}{n^2 t_c}} \overset{p=n}{=} \frac{1}{1 + \dfrac{4(t_s + n t_w)}{n\,t_c}} \;\xrightarrow{\;n\to\infty\;}\; \frac{1}{1 + \dfrac{4t_w}{t_c}}

La eficiencia sube con nn pero se estanca en 1/(1+4tw/tc)1/(1 + 4t_w/t_c) (con los valores de antes, 1/41≈0.02441/41 \approx 0.0244). En términos de Kumar escala pobremente: W=n2=p2W = n^2 = p^2.

Por columnas. Cada procesador tiene una columna completa. Como las dependencias son verticales, todas quedan dentro de la columna: no hay comunicaciones.

T(n,p)=n tcC=p n tc=n2tcT0=0S=n=pE=1T(n,p) = n\,t_c \qquad C = p\,n\,t_c = n^2 t_c \qquad T_0 = 0 \qquad S = n = p \qquad E = 1

Es el diseño ideal en cuanto a eficiencia, pero como p=np = n y W=n2W = n^2, para usar más procesadores el problema tiene que crecer como W=O(p2)W = O(p^2).

En la gráfica de eficiencia escalada de clase (diapositiva 7), con p=np = n las dos curvas caen, y la de filas queda por encima de la de columnas. Con p=np = n atado, ninguna de las dos mantiene el tiempo al multiplicar WW y pp por el mismo factor. El arreglo es el problema 4: desatar pp de nn.

Problema 3: columnas + carga/descarga de datos (p=np = n)

Ahora se cuenta repartir la matriz y recogerla. Un procesador envía a los otros p−1p-1 su columna (nn datos) uno a uno (P2P no optimizado), y al final se recoge igual: 2(p−1)2(p-1) mensajes de nn datos.

T(n,p)=2(p−1)(ts+n tw)+n tc≅2p(ts+n tw)+n tcT(n,p) = 2(p-1)(t_s + n\,t_w) + n\,t_c \cong 2p(t_s + n\,t_w) + n\,t_c
C≅2p2(ts+n tw)+p n tcT0≅2p2(ts+n tw)C \cong 2p^2(t_s + n\,t_w) + p\,n\,t_c \qquad T_0 \cong 2p^2(t_s + n\,t_w)
E≅n2tcp(2p(ts+ntw)+ntc)=p=ntc2(ts+n tw)+tcE \cong \frac{n^2 t_c}{p\big(2p(t_s + nt_w) + nt_c\big)} \overset{p=n}{=} \frac{t_c}{2(t_s + n\,t_w) + t_c}

Isoeficiencia (con W=n2W = n^2):

  • tst_s: n2=W∝Kp2n^2 = W \propto Kp^2 → escalable pero no óptimo (cuadrática).
  • twt_w: n2=W∝K p2n=K W1/2p2⇒W1/2∝Kp2⇒W∝K2p4n^2 = W \propto K\,p^2 n = K\,W^{1/2}p^2 \Rightarrow W^{1/2} \propto Kp^2 \Rightarrow W \propto K^2 p^4 → escalabilidad muy pobre.

Lección: la distribución secuencial desde un nodo arruina un diseño que sin ella era perfecto. En la comparativa de clase, "columnas + E/S" es con diferencia la peor curva.

Problema 4: columnas con p<np < n

Cada procesador tiene n/pn/p columnas (bloques de columnas consecutivas). Sigue sin haber comunicaciones:

T(n,p)=n2ptcC=n2tcT0=0S=pE=1T(n,p) = \frac{n^2}{p}t_c \qquad C = n^2 t_c \qquad T_0 = 0 \qquad S = p \qquad E = 1

Es la generalización del caso por columnas. Ahora pp ya no está atado a nn: mientras p≤np \le n, es perfecto.

Problema 5: filas con p<np < n

Cada procesador tiene n/pn/p filas consecutivas. Solo las filas de los bordes del bloque tienen que comunicarse (con el bloque de arriba y el de abajo): siguen siendo 4 mensajes de nn datos, pero ahora con mucho más cálculo por procesador.

T(n,p)=n2ptc+4(ts+n tw)C=n2tc+4p(ts+n tw)T0=4p(ts+n tw)T(n,p) = \frac{n^2}{p}t_c + 4(t_s + n\,t_w) \qquad C = n^2 t_c + 4p(t_s + n\,t_w) \qquad T_0 = 4p(t_s + n\,t_w)
E=n2tcn2tc+4p(ts+n tw)=11+4p(tsn2tc+twn tc)E = \frac{n^2 t_c}{n^2 t_c + 4p(t_s + n\,t_w)} = \frac{1}{1 + 4p\left(\dfrac{t_s}{n^2 t_c} + \dfrac{t_w}{n\,t_c}\right)}
  • tst_s: n2=W∝Kpn^2 = W \propto Kp → escalable óptimo.
  • twt_w: n2=W∝K p n=KW1/2p⇒W∝K2p2n^2 = W \propto K\,p\,n = K W^{1/2} p \Rightarrow W \propto K^2 p^2 → no óptimo, isoeficiencia cuadrática.

La eficiencia escalada baja despacio (≈ 0.55 con p=512p = 512): mucho mejor que con p=np = n.

Problema 6: el problema 4 + carga/descarga

Repartir los bloques de n2/pn^2/p datos desde un nodo y recogerlos, P2P no optimizado:

T(n,p)=2(p−1)(ts+n2ptw)+n2ptc≅2p(ts+n2ptw)+n2ptcT(n,p) = 2(p-1)\left(t_s + \frac{n^2}{p}t_w\right) + \frac{n^2}{p}t_c \cong 2p\left(t_s + \frac{n^2}{p}t_w\right) + \frac{n^2}{p}t_c
C≅2p2ts+2p n2tw+n2tcT0≅2p2ts+2p n2twC \cong 2p^2 t_s + 2p\,n^2 t_w + n^2 t_c \qquad T_0 \cong 2p^2 t_s + 2p\,n^2 t_w
E≅n2tc2p2ts+2p n2tw+n2tcE \cong \frac{n^2 t_c}{2p^2 t_s + 2p\,n^2 t_w + n^2 t_c}
  • tst_s: W∝Kp2∈O(p2)W \propto Kp^2 \in O(p^2).
  • twt_w: W=n2∝K p n2⇒1∝KpW = n^2 \propto K\,p\,n^2 \Rightarrow 1 \propto Kp → nn se cancela: no es escalable. Por mucho que crezca la matriz, el reparto cuesta tanto como el propio problema.

(En la diapositiva hay una errata en el paso intermedio de EE, que pone n tcn\,t_c donde debería poner n2tcn^2 t_c; el resultado final es el correcto.)

Problema 7: el problema 5 + carga/descarga

T(n,p)=2(p−1)(ts+n2ptw)+n2ptc+4(ts+n tw)≅n2ptc+2ts(p+2)+2tw(n2+2n)T(n,p) = 2(p-1)\left(t_s + \frac{n^2}{p}t_w\right) + \frac{n^2}{p}t_c + 4(t_s + n\,t_w) \cong \frac{n^2}{p}t_c + 2t_s(p+2) + 2t_w(n^2 + 2n)
T0=2p ts(p+2)+2p tw(n2+2n)T_0 = 2p\,t_s(p+2) + 2p\,t_w(n^2 + 2n)
E≅11+2p2tsn2tc+4p twn tc+2p twtcE \cong \frac{1}{1 + \dfrac{2p^2 t_s}{n^2 t_c} + \dfrac{4p\,t_w}{n\,t_c} + \dfrac{2p\,t_w}{t_c}}
  • tst_s: W∝Kp2W \propto Kp^2.
  • twt_w: W∝K W p⇒1∝KpW \propto K\,W\,p \Rightarrow 1 \propto Kp → no escala (el término 2p tw/tc2p\,t_w/t_c de EE no depende de nn).

Comparativa final (eficiencia escalada)

DiseñoComportamiento
Bloques de columnas, p<np < nEsca=1E_{sca} = 1: perfecto
Bloques de filas, p<np < nBaja muy despacio
Filas, p=np = nBaja más rápido
Columnas, p=np = nBaja todavía más
Cualquiera + E/SSe desploma: no escala

Diseño de algoritmos paralelos

Problema 1: procesado de nn imágenes en 5 fases

Enunciado: n≫1n \gg 1 imágenes; cada una pasa, en orden, por lectura, corrección de brillo, detección de bordes, compresión y almacenamiento. pp procesadores. Aplicar las dos primeras etapas de Foster y decir qué patrón describe la solución.

1. Descomposición: funcional. El trabajo sobre cada imagen se divide en fases que hacen operaciones distintas. Se definen 5 tipos de tareas: TLT_L (lectura), TBT_B (brillo), TET_E (bordes), TCT_C (compresión) y TAT_A (almacenamiento). Para cada imagen IiI_i:

TL(Ii)→TB(Ii)→TE(Ii)→TC(Ii)→TA(Ii)T_L(I_i) \to T_B(I_i) \to T_E(I_i) \to T_C(I_i) \to T_A(I_i)

2. Comunicaciones: locales, estáticas y regulares: cada fase envía la imagen procesada solo a la siguiente. No hay dependencias entre imágenes distintas.

Patrón: pipeline (segmentación). Mientras TBT_B trata la imagen 1, TLT_L ya lee la imagen 2, etc. Una vez lleno el cauce, sale una imagen por "ciclo".

Problema 2: índice invertido sobre nn documentos

Enunciado: construir, para cada palabra, la lista de documentos donde aparece (p. ej. casa→{D0,D7,D100}casa \to \{D_0, D_7, D_{100}\}). Dos primeras etapas y patrón.

1. Descomposición del dominio sobre los datos de entrada: se reparten los nn documentos entre las tareas.

2. Comunicaciones en tres fases:

  1. Map: cada tarea procesa sus documentos de forma independiente y genera pares (palabra,documento)(palabra, documento). Sin comunicación.
  2. Shuffle (redistribución): se reúnen todos los pares con la misma clave (palabra) en la misma tarea. Es una comunicación global, todos con todos (cada tarea puede tener pares para cualquier otra).
  3. Reduce: cada tarea combina las listas de sus palabras y obtiene la parte del índice global (nuevo reparto de trabajo: ahora por palabras).

Patrón: MapReduce.

Problema 3

Es el problema 22 del boletín de exámenes (normalización por filas). Está resuelto en Problemas de examen resueltos.