Saltar a contenido

Ejemplo Benchmarking


Ejemplo Benchmarking

/*  
 * This Scala source file was generated by the Gradle 'init' task. */package taller  
import org.scalameter._  
import common._  
import org.scalameter.Warmer.Default  

object App {  
  def main(args: Array[String]): Unit = {  

    // Se crea un arreglo de 100 millones de enteros para realizar las pruebas de rendimiento
    val arr = (1 to 100000000).toArray  

    // Medición del tiempo de ejecución secuencial (un solo hilo)
    val t1 = withWarmer(new Default) measure {  
      val res = sumaArray(arr,0, arr.length)  
      //println(res)  
    }  
    println("Tiempo secuencial "+t1)  

    // Medición del tiempo de ejecución con 2 hilos (paralelismo)
    val t2 = withWarmer(new Default) measure {  
      val m = arr.length/2  
      val (r1,r2) = parallel(  
        sumaArray(arr,0, m) ,  
          sumaArray(arr,m, arr.length)  
      )  
      //println(r1+r2)  
    }  
    println("Tiempo con 2 hilos "+t2)  

    // Medición del tiempo de ejecución con 4 hilos (paralelismo)
    val t3 = withWarmer(new Default) measure {  
      val n = arr.length  
      val (r1,r2,r3,r4) = parallel(  
        sumaArray(arr,0, n/4) ,  
        sumaArray(arr,n/4, n/2),  
        sumaArray(arr,n/2, 3*n/4),  
        sumaArray(arr,3*n/4, n)  
      )  
      //println(r1+r2+r3+r4)  
    }  
    println("Tiempo con 4 hilos "+t3)  

  }  

  // Función que suma los elementos de un arreglo en un rango [s, t)
  // Utiliza recursión de cola para eficiencia
  def sumaArray(arr:Array[Int], s:Int, t:Int):Long= {  
    @scala.annotation.tailrec  
    def filtroArrayAux(i:Int, acc:Long):Long = {  
      if (i >= t) acc  
      else filtroArrayAux(i+1, arr(i)+acc)  
    }  
    filtroArrayAux(s,0L)  
  }  

}

Al ejecutar encontramos

Tiempo secuencial 26.420437 ms
Tiempo con 2 hilos 15.240116 ms
Tiempo con 4 hilos 13.921229 ms

Conceptos teóricos involucrados

  • Benchmarking: Proceso de medir el rendimiento de un programa bajo condiciones controladas. En este caso se usa la librería scalameter para obtener mediciones precisas.
  • Paralelismo: Ejecución simultánea de tareas para aprovechar múltiples núcleos del procesador. Se usa la función parallel del paquete common para dividir el trabajo.
  • Speedup: Relación entre el tiempo secuencial y el tiempo paralelo. Para 2 hilos: \(26.42 / 15.24 \approx 1.73\), para 4 hilos: \(26.42 / 13.92 \approx 1.90\).
  • Ley de Amdahl: Establece que la ganancia máxima de rendimiento está limitada por la porción secuencial del programa. En este caso, la suma es altamente paralelizable, pero la sobrecarga de creación de hilos y sincronización reduce la eficiencia.
  • Recursión de cola: Técnica de programación funcional que permite que el compilador optimice la recursión evitando desbordamiento de pila. Se usa @scala.annotation.tailrec para garantizar esta optimización.

Tabla de resumen de conceptos

Concepto Descripción
Benchmarking Medición del tiempo de ejecución de un programa bajo condiciones controladas
Paralelismo Ejecución simultánea de tareas en múltiples núcleos
Speedup Relación entre tiempo secuencial y tiempo paralelo
Ley de Amdahl Límite teórico de la ganancia de rendimiento debido a la parte secuencial
Recursión de cola Optimización de recursión para evitar desbordamiento de pila
ScalaMeter Librería para realizar benchmarks precisos en Scala
Función parallel Función que ejecuta tareas en paralelo y devuelve una tupla con los resultados

Comentarios adicionales

  • La ganancia de rendimiento al pasar de 2 a 4 hilos es pequeña (de 15.24 ms a 13.92 ms), lo que sugiere que el cuello de botella no es solo computacional, sino también de acceso a memoria (el arreglo es grande y puede haber contención en el bus de memoria).
  • Para obtener un mejor speedup, se podría considerar un enfoque de fork-join más sofisticado o usar estructuras de datos que permitan mejor localidad de caché.
  • El uso de withWarmer(new Default) calienta la JVM antes de medir, lo que evita que los resultados se vean afectados por la compilación Just-In-Time (JIT).