Benchmarking - stefano-sosac/arquitectura-de-computadoras GitHub Wiki
Rendimiento (Performance)
El rendimiento de una computadora se puede definir como cuánto tiempo toma realizar una acción o cuántas cosas pueda hacer en un determinado tiempo. En ambos casos, el indicador principal con el cual se parte es el tiempo de ejecución de un programa. Hennessy & Patterson mencionan que la frase "X es más rápido que Y" responde a la caracterización numérica de brindar una relación entre X e Y. Entonces, la relación entre los tiempos de ejecución de X e Y se da por la siguiente ecuación:
En concreto, Hennessy & Patterson plantean que la mejor forma de medir el performance es el tiempo de ejecución de programas reales. Estos programas incluyen actividades como almacenamiento, acceso a memoria, actividades de I/O, overhead por el sistema operativo, entre otros.
La motivación principal de evaluar el rendimiento es la comparación entre computadoras para evaluar una nueva. Esto permite al usuario entender una perspectiva global sobre qué tan bueno es un nuevo sistema utilizando programas que ya involucran diferentes características de una computadora. Estos programas se conocen como "Benchmarks"
Benchmarks
Son programas que tiene como fin brindar información acerca del rendimiento acerca de diferentes sistemas de cómputo. Los benchmarks son codificados en lenguajes como C o C++. Cada benchmark está diseñado para evaluar puntos clave de un sistema de cómputo por lo que típicamente se utiliza un conjunto de benchmarks para evaluar particularidades del sistema. Actualmente, SPEC (Standard Performance Evaluation Corporation) ha trabajado un conjunto de becnhmarks para brindar las mejores referencias en el uso de aplicaciones de sistemas de cómputo (www.spec.org). La idea principal es tener una referencia para uniformizar qué tanto es mejor una computadora en comparación con otra a través de un ratio (o división de tiempos de ejecución) cómo se vió en la ecuación anterior.
Si consideramos que diferentes benchmarks pueden brindar información sobre el desempeño de diferentes elementos del sistema, el análisis por benchmarks podría ser un poco más complicado. Por ejemplo, un benchmark se puede enfocar directamente en evaluar la respuesta de operaciones I/O con el procesador mientras que otro puede enfocarse en el tiempo invertido en accesos a memoria caché/memoria principal. Esto incluso podría ser más retador si es que se trabajan con diferentes sistemas operativos. En ese sentido, la propuesta es analizarlo a través de un ratio que generalice el rendimiento total a través del cálculo de la media geométrica. Por tanto:
Siendo $n$, $r_i$ y $R$ el número de benchmarks, el ratio de cada benchmark y el ratio total, respectivamente.
Ejemplo
Se requiere hacer la adquisición de un nuevo sistema de cómputo. Para ello, se han medido los tiempos de ejecución de los benchmark test_cache, image_visualization y storage_latency en el sistema que se desea reemplazar. Entre las opciones de adquisición se cuenta con las computadoras A y B en las cuales también se han medido los tiempos de ejecución de los benchmarks codificados. Los resultados se adjuntan en la siguiente Tabla:
| Benchmark | Tiempo de Referencia (us) | Tiempo PC A (us) | Tiempo PC B (us) |
|---|---|---|---|
| test_cache | 7.02 | 4.12 | 5.97 |
| image_visualization | 6.62 | 3.72 | 2.70 |
| storage_latency | 4.72 | 3.91 | 1.81 |
Se pide evaluar qué computadora sería la más conveniente para reemplazar al sistema actual.
Solución
Primero se evaluará el ratio de cada benchmark:
| Benchmark | Ratio A ($r_{i}$) | Ratio B ($r_{i}$) |
|---|---|---|
| test_cache | 1.70 | 1.17 |
| image_visualization | 1.77 | 2.45 |
| storage_latency | 1.20 | 8.54 |
Aplicando la fórmula para hallar el ratio general: $$(1.70 \times 1.77 \times 1.20)^{\frac{1}{3}} = 1.53$$ $$(1.17 \times 2.45 \times 1.23)^{\frac{1}{3}} = 2.90$$
La computadora A es, en promedio, 1.53 más rápida que el sistema actual, mientras que la computadora B es, en promedio, 2.90 más rápida que la referencia. Por tanto, para este caso particular, la computadora B sería la más adecuada.
Variaciones del tiempo de ejecución
De forma práctica, el tiempo de ejecución no suele ser estable sobretodo cuando el sistema operativo tiene más componentes de hardware y softwares complejos que utilizar. Analicemos el siguiente ejemplo:
Se le brinda un código en Python que calcula el factorial de forma iterativa. La implementación de este código está diseñado específicamente para ser de alta carga computacional y no se encuentra optimizado. El código ejecutará la función 50 veces y se mostrará el tiempo de ejecución de todas las iteraciones:
import time
import matplotlib.pyplot as plt
# Definimos la función para calcular factorial de manera iterativa
def factorial_iterative(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
# Número para el cual calcularemos el factorial
n = 500
# Listas para guardar los tiempos de ejecución
times_iterative = []
# Realizamos 50 ejecuciones
for _ in range(50):
# Medir tiempo para el método iterativo
tic = time.perf_counter()
factorial_iterative(n)
toc = time.perf_counter()
times_iterative.append(1e6*(toc - tic))
# Generar gráfica
plt.figure(figsize=(10, 5))
plt.plot(times_iterative, label='Factorial Iterativo')
plt.xlabel('Ejecución #')
plt.ylabel('Tiempo (us)')
plt.title('Tiempos de Ejecución de Factorial')
plt.grid()
plt.legend()
plt.show()
plt.close()
Al ejecutar este código en Google Colab, se obtendrá el siguiente resultado:
Tal como se observa, los tiempos de ejecución no son muy estables; por tanto, es necesario utilizar un único que valor que sea lo suficientemente representativo del tiempo de ejecución del sistema de cómputo.
Linda Null menciona que ante diferentes tiempos de ejecución se suele tomar la mediana, otros autores sugieren el uso de la media armónica. Para fines prácticos, ambos dan resultados que minimizan el impacto de los valores atípicos por lo que son válidos para calcular el tiempo de ejecución.
Ahora se le invita a realizar los siguientes ejercicios:
Ejercicios
Ejercicio 1
A continuación, se le brinda un conjunto de Benchmarks:
import numpy as np
def benchmark_float_operations(size=1000000):
a = np.random.rand(size)
b = np.random.rand(size)
return a * b
def benchmark_integer_operations(count=1000000):
result = 0
for i in range(count):
result += i
return result
import os
def benchmark_disk_io():
data = 'a' * 1024 * 1024 # 1 MB de datos
with open('test_file.txt', 'w') as f:
for _ in range(10): # Escribe 10 MB de datos
f.write(data)
os.remove('test_file.txt')
Se le pide:
- Identificar qué componente del sistema de cómputo se está evaluando en cada benchmark
- Ejecutar y extraer los tiempos de ejecución característicos de la función en Google Colab. Puede utilizar 50 iteraciones y extraer la mediana.
- Ejecutar y extraer los tiempos de ejecución característicos de la función en dos computadoras distintas
- Hacer un análisis basado en los ratios relativos y general para hallar en qué computadora se ejecuta mejor cada benchmark y qué computadora es mejor (o peor) tomando como referencia lo ejecutado en Google Colab.