Ejercicio de Paralelización¶
Instrucciones¶
Descargar el repositorio plantilla funcional¶
git clone git@github.com:cardel/plantilla-funcional.git
Borrar el repositorio de git¶
rm -rf .git
Ejercicio: Cálculo de Promedio Ponderado¶
El promedio ponderado va a tomar un arreglo de notas y un arreglo de número de créditos.
Datos de Ejemplo¶
\[
\begin{aligned}
\texttt{notas} = \{4.2, 4.3, 1.2\} \\
\texttt{creditos} = \{4, 3, 2\}
\end{aligned}
\]
Proceso de Cálculo¶
Primero sacar los intermedios:
\[
\texttt{intermedio} = \{4.2 \times 4, 4.3 \times 3, 1.2 \times 2\}
\]
Sumamos los créditos:
\[
\texttt{sumcreditos} = 4 + 3 + 2 = 9
\]
Sumamos los intermedios:
\[
\texttt{sumintermedio} = 4.2 \times 4 + 4.3 \times 3 + 1.2 \times 2 = 32.1
\]
Finalmente el promedio ponderado:
\[
\frac{\texttt{sumintermedio}}{\texttt{sumcreditos}} = \frac{32.1}{9} = 3.56667
\]
Ejercicio de Paralelización: Promedio Ponderado¶
Solución Implementada¶
Clase Ponderado¶
class Ponderado {
def poderacion(notas: Array[Double], creditos: Array[Int], ini: Int, fin: Int): Double = {
(ini until fin).map(i => notas(i) * creditos(i)).sum
}
def sumaCreditos(creditos: Array[Int], ini: Int, fin: Int): Int = {
(ini until fin).map(i => creditos(i)).sum
}
}
Clase Principal¶
import scala.util.Random
import common._
object App {
def main(args: Array[String]): Unit = {
val objPonderado = new Ponderado()
val n = 10000000
val r = new Random()
// Generación de datos de prueba
val arrayNotas = (1 to n).map(x => r.nextDouble() * 5).toArray
val arrayCreditos = (1 to n).map(x => r.nextInt(5) + 1).toArray
// Versión Secuencial
val res = objPonderado.poderacion(arrayNotas, arrayCreditos, 0, n) /
objPonderado.sumaCreditos(arrayCreditos, 0, n)
println(s"El ponderado secuencial es: $res")
// Paralelización con Parallel (2 hilos)
val (pond1, pond2) = parallel(
objPonderado.poderacion(arrayNotas, arrayCreditos, 0, n/2),
objPonderado.poderacion(arrayNotas, arrayCreditos, n/2, n)
)
val (suma1, suma2) = parallel(
objPonderado.sumaCreditos(arrayCreditos, 0, n/2),
objPonderado.sumaCreditos(arrayCreditos, n/2, n)
)
println(s"El ponderado paralelo es: ${(pond1 + pond2) / (suma1 + suma2)}")
// Paralelización con Task (4 hilos)
val t1 = task(objPonderado.poderacion(arrayNotas, arrayCreditos, 0, n/2))
val t2 = task(objPonderado.poderacion(arrayNotas, arrayCreditos, n/2, n))
val t3 = task(objPonderado.sumaCreditos(arrayCreditos, 0, n/2))
val t4 = task(objPonderado.sumaCreditos(arrayCreditos, n/2, n))
val pond3 = t1.join()
val pond4 = t2.join()
val suma3 = t3.join()
val suma4 = t4.join()
println(s"El ponderado paralelo con task es: ${(pond3 + pond4) / (suma3 + suma4)}")
}
}
Tabla de Resumen¶
| Componente | Descripción | Implementación | Paralelización |
|---|---|---|---|
| Clase Ponderado | Contiene métodos para cálculo ponderado | poderacion() y sumaCreditos() |
- |
| Generación de Datos | Crea arrays de prueba grandes | n = 10,000,000 elementos |
- |
| Versión Secuencial | Cálculo en un solo hilo | Llamadas directas a métodos | Sin paralelismo |
| Parallel (2 hilos) | Uso de abstracción parallel | Divide trabajo en 2 partes | 2 hilos por operación |
| Task (4 hilos) | Uso de abstracción task | Control granular de hilos | 4 hilos total |
| Partición de Datos | División del array para procesamiento | Rangos [0, n/2) y [n/2, n) |
Balance de carga |
Características de la Solución¶
- Escalabilidad: Maneja grandes volúmenes de datos (10 millones de elementos)
- Múltiples Estrategias: Implementa secuencial, parallel y task
- Balance de Carga: División equitativa del trabajo entre hilos
- Verificación: Comparación de resultados entre diferentes implementaciones
Ventajas de la Paralelización¶
- Aceleración: Procesamiento simultáneo de diferentes segmentos
- Eficiencia: Mejor uso de recursos en sistemas multinúcleo
- Flexibilidad: Diferentes niveles de granularidad con parallel vs task