ArchiTecnologia

Aprendizaje abierto. Conocimiento libre.

ArchiTecnologia
HardwareTutorial

CPU: introducción a las unidades de rendimiento y cálculos

Seguramente, cuando hayas estado ojeando benchmarks, o características de una CPU, habrás visto multitud de parámetros o unidades de rendimiento. Quizás conozcas lo que significan muchas de ellas, pero… ¿sabes cómo se calculan? Lo cierto es que no hay demasiadas webs donde muestren todo esto de una forma clara. Por eso me he decidido a publicar este tutorial sobre cálculos de rendimiento para procesadores.

Además de las fórmulas y cálculos habituales de rendimiento, también mostraré las diferencias de alguna que otra que veo que suele generar confusión, dadas las preguntas que me hacen a veces…

CPU: formulas y cálculos

AMD Am29k die shot

Seguramente estés leyendo mucho estos últimos días sobre el «heterogeneous multi-processing» o multiprocesamiento heterogéneo (mal llamado big.LITTLE, ya que ese es el término específico para ARM y no el genérico), que no es lo mismo que la computación heterogénea, en la que se usan diferentes procesadores a los que se les «encomiendan» aquella tarea que son capaces de procesar de forma más rápida o eficiente.

Próximamente me gustaría dedicar un artículo íntegro al multiprocesamiento heterogéneo.

Aquí surgen algunas cuestiones como ¿Por qué hacer que la CPU se encargue de ciertos cálculos si una GPGPU lo haría más rápido? ¿por qué no usar un DSP en ciertas tareas específicas en las que le ganaría a una CPU?

Por ejemplo, ¿sabías que una CPU suele consumir un 90% de la energía en mover datos de un lugar a otro y solo un 10% en procesarlos? En cambio, en una GPU el consumo para moverlos baja a un 70% y para procesarlos emplea el 30%. Por eso pueden ser más interesantes para ciertas aplicaciones, consiguiendo una mayor eficiencia FLOPS/w.

Pues bien, todo esto tiene mucho que ver con los cálculos que vamos a ver a continuación… (aunque yo me centraré en la CPU)

Algunas unidades

Brevemente, antes de continuar con los cálculos me gustaría dejar claro qué son los MIPS y FLOPS, para aquellos lectores que no lo conozcan aún:

  • IPS: es la unidad de referencia que se suele usar fuera del mundo HPC. Son las siglas de Instructions Per Second (generalmente se suele usar MIPS = Millions of IPS), es decir, las instrucciones por segundo que una unidad de procesamiento puede realizar. Cada modelo de procesador tendrá un rendimiento diferente, al igual que ocurre con los FLOPS. Por ejemplo, el AMD Threadripper 3990X puede desarrollar 2.356.230 MIPS @ 4.35 GHz, mientras un Zilog Z80 podía llegar a 1.16 MIPS @ 8 Mhz. Se entiende que con overclocking se puede llegar a incrementar.
  • IPC: son las siglas de Instructions Per Cycle, o instrucciones por ciclo de reloj que una unidad puede realizar. Es decir, en vez de tomar como referencia el tiempo, como en el IPS, se toma un ciclo de reloj.
  • CPI: suele confundirse con las anteriores, pero en esta ocasión se denomina Cycles Per Instruction, es decir, los ciclos de reloj que necesita una unidad para ejecutar una instrucción. Esta medida es muy dispar, ya que dependerá también del tipo de instrucción. No todas las instrucciones tardan los mismos ciclos, y cada procesador tendrá un tiempo de respuesta diferente. Algunas pueden realizarse en 1, otras en 3, etc. Por ejemplo, una instrucción de carga (load) puede demorarse 5 ciclos, mientras una de salto (jump) podría tardar 3.
  • FLOPS: es el acrónimo de Floating Point Operations Per Second. Es decir, las operaciones de coma flotante que un procesador puede realizar en un solo segundo. Esta unidad es especialmente importante en aplicaciones científicas, y no tanto en otro tipo de software donde priman los enteros. Por ejemplo, el IBM Summit alcanza 200 PFLOPS (PetaFLOPS), lo que quiere decir que puede realizar 200.000.000.000.000.000 cálculos de coma flotante en un segundo. Además, debes saber que se suele relacionar esta unidad con el vatio (FLOPS/w) para medir la eficiencia energética de una máquina.
  • Frecuencia de reloj (hercio): no hay que confundirlo con nada de lo anterior. Esta unidad determina la velocidad de conmutación de los transistores de un procesador. Si una CPU tiene 3.2 Ghz no quiere decir que pueda realizar 3.200.000.000 operaciones en un segundo, sino que trabajará a ese «ritmo». Ahora bien, si se hace trabajar un chip a mayor frecuencia, tanto los FLOPS como IPS se verían beneficiados.

A la hora de elegir una unidad con mayor rendimiento, algunos caen en el mito de la frecuencia de reloj (megahertz myth). Actualmente no es un factor determinante para comparar productos, ya que un microprocesador con menor frecuencia de reloj podría rendir más que uno con mayor frecuencia de reloj. Esto es así debido al paralelismo, al IPC, etc.

Existen más, por ejemplo, SUPS (Synaptic Update Per Second) o CUPS (Connections Updates Per Second) usada para medir rendimiento en redes neuronales artificiales, etc.

Cálculos

Después de haber explicado lo básico, vamos con las fórmulas

Frecuencia

Deberías conocer las diferencias entre frecuencia (f), ciclo o periodo (T):

De aquí se pueden sacar algunas conclusiones, como la repercusión de la profundidad y la lógica en la frecuencia de una CPU:

frecuencia

Y si te preguntas cómo se puede mejorar la frecuencia, además de mejorando el switching de los transistores mediante técnicas de fabricación, le deberías prestar atención a la profundidad de la pipeline:

frecuencia

Tiempo de ejecución

El tiempo que tarda en ejecutarse un programa se puede calcular así:

Tiempo ejecución

Es decir, el tiempo será igual al número de instrucciones necesarias para dicho programa (NI), por el número de ciclos necesarios  para ejecutar cada instrucción (CPI) partido por el tiempo que tarda en producirse un periodo de reloj. Como el número de instrucciones de un programa no se puede cambiar desde el lado del hardware, lo que se busca es reducir el CPI y aumentar la frecuencia para reducir el tiempo de ejecución.

Rendimiento y tiempo de ejecución

El rendimiento resulta de hacer la inversa del tiempo de ejecución:

rendimiento

O también:

Performance = 1 / Tiempo de ejecución = (Frecuencia · IPC) / Recuento de instrucciones

Aunque se suele expresar en tiempo de CPU con la fórmula:

tiempo CPU

La primera fórmula para una CPU y la segunda para un sistema paralelo, siendo P el número de procesadores instalados en el sistema. En cuanto al término RI, es el recuento de instrucciones (es lo mismo que NI, solo que he empleado un término diferente en esta fórmula).

Por ejemplo, imagina un chip X que trabaja a 2 Ghz, con un IPC de 16 DP y 32 SP, y siendo un quadcore. Si se supone que va a ejecutar un programa compuesto por 800 instrucciones y que trabajará en doble precisión:

ejemplo

Con estas fórmulas también se puede comparar el rendimiento de dos computadoras, para evaluar cuánto más rápida es una respecto a la otra:

Rendimiento comparado

Rendimiento por instrucción (IPC)

Es el resultado de multiplicar la cantidad de instrucciones que se necesitan para un programa dado y el promedio de instrucciones por ciclo. Por tanto, las comparativas entre dos máquinas se deberían hacer siempre usando el mismo programa de referencia o benchmark:

IPC

CPI

En cuanto al CPI, también se puede calcular fácilmente mediante la siguiente fórmula:

CPI

IPS

Para calcular las instrucciones por segundo de una CPU se puede aplicar la fórmula:

mips

Como la mayoría de microarquitecturas están segmentadas (pipeline) y surgen dependencias de instrucciones, predicción, etc., eso supone que se debe llevar el vaciado del cauce en caso de que haya algún problema. Por tanto, no es tan sencillo como aplicar la anterior fórmula.

FLOPS

Para los cálculos de coma flotante en un segundo:

flops

El primer caso para un sistema simple y el segundo para uno paralelo. Por cierto, habría que diferenciar si se hacen en precisión simple o doble… También hay que diferenciar entre FLOPS nativos y relativos (normalizados). Para esto también me gustaría dedicar un artículo, por el momento quédate con el cálculo. Así no se alargan tanto los artículos y se hacen tan pesados. Lo mismo digo para otros cálculos que me gustaría analizar como el parallel speedup, la ley de Amdahl, ley de Gustafson, etc.

Speed-up (aceleración)

Según la Ley de Amdahl, la ganancia de rendimiento o speedup que se consigue mejorando un recurso de un computador en un factor p es:

speedup

Donde f es la proporción de tiempo en que dicha mejora no se usa en las aplicaciones que se ejecutan. Por tanto, por mucho que mejore el recurso (p), la mejora no será mejor que 1/f. Cuando se mejora un cuello de botella, f se hace más pequeña. En cambio, otro tipo de ganancias donde las aplicaciones hacen escaso uso, f será próximo a 1 y la ganancia pequeña.

Aplicando esto a un sistema segmentado, tenemos que:

speedup CPU

Ley de Gustafson

Frente al «pesimismo» de la Ley de Amdahl sobre la escalabilidad de un sistema, donde el programa a tratar se puede dividir en dos partes: una paralelizable (p) y otra secuencial (s). Eso hace que el cuello de botella de la secuencial tienda a cero cuando el tamaño del programa aumenta. Para calcular la aceleración en este caso, considerando que el programa ha crecido en igual proporción que el número de procesadores, el speedup en un sistema (siendo N el número de procesadores) es:

Gustafson

Esto nos llega a pensar en la importancia del balanceo o distribución de la carga de trabajo en un sistema paralelo o eficiencia:

eficiencia

Relacionando esto con la Ley de Amdahl se puede deducir el factor de aceleración:

eficiencia

Eso sería la fracción de tiempo usada por los procesadores durante la computación. Se deduce que, para un mismo programa, si se aumenta el número de procesadores del sistema, se produce un decremento de la eficiencia, ya que se reparte el trabajo entre cada uno de ellos y el tiempo de uso de cada uno de ellos es menor.

Si quisieras mantener constante la eficiencia, en lugar de mantener el tiempo de ejecución como constante, se podría buscar el equilibrio de la eficiencia mediante una función de isoeficiencia. Esa fórmula busca el tamaño adecuado del programa o problema (n) para mantener constante la eficiencia al incrementar p (nº procesadores), teniendo en cuenta el tiempo de sobrecarga (overhead).

isometricas eficiencia

Al ser E inmutable en este caso, al ser isoeficiencia, se puede despejar, y también sustituir la constante E/(E-1) por K como se aprecia en la última fórmula…

Demanda de memoria de un sistema

La demanda de memoria de un sistema se puede estimar mediante las instrucciones de coma flotante:

Memoria

Casi todos se centran en la velocidad, latencia y ancho de banda de la memoria. Esto es importante, sí, es cierto. Pero muchas veces se olvida otro factor clave que puede ser incluso más importante para el rendimiento, y si no que se lo digan al Apple M1… Me estoy refiriendo a la tasa de fallos y aciertos cuando se pretende acceder a algún dato de la memoria:

Miss rate = Nº de fallos / Nº total de acceso a memoria

Hit Rate = Nº de aciertos / Nº total de acceso a memoria

Ten en cuenta que, si una CPU necesita 1 ciclo de reloj para acceder a su cache, y 100 ciclos para acceder a la memoria RAM o principal, entonces eso quiere decir que si se optimiza un sistema para aumentar la tasa de aciertos (p.e.: aumentando la cache), se conseguirá un aumento considerable del rendimiento incluso si el ancho de banda y latencia no son muy buenos… Es decir, es una forma de eliminar esas penalizaciones o sanciones energéticas de ir a buscar datos a la memoria principal.

La jerarquía de memoria se ha perfeccionado para ofrecer memorias muy rápidas, como los registros de la CPU, o la caché, que puedan paliar los efectos de cuello de botella y latencia de la memoria principal (RAM) y de los medios de almacenamiento secundarios. Para hacerte una idea, un registro de 64-bit es aproximadamente 200 veces más rápido que la SDRAM (0.25 ns frente a 50 ns), y 10.000 veces más eficientes energéticamente (0.1 pJ frente a 1000 pJ).

Por otro lado, cuando se trata de la memoria principal, generalmente tienen una frecuencia de X Mhz a la que operan si son SDR, en cambio, las DDR se doblaría. Por ejemplo, si funciona a 3200 Mhz (3200 MT/s o Megatransfers per second o meillones de transferencias por segundo), realmente está operando a una frecuencia de reloj nominal de 1600 Mhz.

Para el cálculo de la freceuncia real o basal, se obtiene de:

Frecuencia real = (Frecuencia · 8) / 64 / 4

Frecuencia real = Frecuencia / 32

Siempre se entiende que la frecuencia se expresa en Mhz. Por ejemplo, para una DDR 3200 Mhz seria:

3200 / 32 = 100 Mhz

Para el ancho de banda, como ocurriría con cualquier bus, se puede calcular teniendo en cuenta el número de canales máximos (Single Channel, Dual Channel,…), el ancho del bus en bits que tiene por cada canal, el número de datos por ciclo de reloj, y la frecuencia de reloj a la que opera.

Por ejemplo, en un módulo DDR4 tiene un bus de 64-bit, con 2 transferencias por ciclo de reloj del controlador de memoria (MMU), ya que es DDR, frente a SDR. Es decir, si fuese DDR4-3200, sería 1600 Mhz (memclk) y un ancho de banda de 3200 Gbps. Por tanto, para calcular el ancho de banda máximo teórico de esta RAM, se puede usar:

Ciclos por segundo · 2 · 64 · Nº de canales

Si se aplican los datos de la DDR4 del ejemplo, y se tiene en cuenta que es un sistema DC (DualChannel):

1.600.000.000 · 2 · 64 · 2 = 409.600.000.00 bits por segundo

Es decir, serían 51.2 GB/s de ancho de banda.

Las memorias flash o de estado sólido (SSD), se comportan de forma similar a las volátiles, por tanto, todas estas fórmula se pueden adaptar para ellas. En cambio, en los HDD, la latencia debe ser calculada de forma diferente.

Por ejemplo, imagina un disco duro de 7200 RPM que quiere acceder a un dato. En este caso, una vez el cabezal ha alcanzado la pista correcta, se debe esperar a que el sector deseado gire debajo del cabezal de lectura/escritura. Esto es lo que se conoce como latencia rotacional o retraso de rotación. Se estima que generalmente supone la mitad del tiempo de rotación, por lo que se podría calcular así:

Media de la latencia rotacional = 0.5 rotación / (nº RPM / 60)

= 0.5 / (7200/60) = 4.16 ms

No obstante, ten en cuenta que el buffer que suelen tener estos discos duros, o las memorias de estado sólido de los SSHD, suelen contribuir a reducir los tiempos de accesos actuando como memorias intermedias.

Cómo mejorar el rendimiento

troubleshooting, servicio técnico

Mejorar el rendimiento de una computadora no es tan sencillo en la práctica, pero a nivel teórico pasaría por optimizar el software, mejorar el paralelismo de procesamiento de la CPU para que ejecute más instrucciones por ciclo, intentar mantener todas las unidades de ejecución ocupadas mediante optimización del compilador o mediante técnicas como el multithreading, mejorando el ancho de banda y latencia para los accesos de memoria y E/S.

«Hasta ahora, la mayoría del software ha sido como música escrita para un solista; con la generación actual de chips estamos adquiriendo un poco de experiencia con duetos y cuartetos y otros pequeños conjuntos; pero componer una obra para una gran orquesta y coro es un desafío diferente.»

Brian Hayes, 2007

  • Algoritmos: afectan directamente al recuento de instrucciones y CPI. El algoritmo del software determinará la cantidad  de instrucciones del programa que se han de ejecutar y el tipo de instrucciones necesarias (ya sabes que algunas son más pesadas y pueden tomar más ciclos que otras). Por ejemplo, algunas operaciones de coma flotante o divisiones toman más ciclos que otras más simples…
  • Lenguaje de programación: también afecta directamente al recuento de instrucciones necesarias para ejecutar un programa y al CPI. Las declaraciones en cada lenguaje se traducen en una serie de instrucciones para el procesador, así que elegir un buen lenguaje mejorará el rendimiento. Y no solo eso, los lenguajes compilados (C, C++, COBOL, FORTRAN…) tienen a tener un mejor rendimiento frente a los interpretados, ya que éstos últimos necesitan de un intérprete (Java, Python, Perl,…), así como más llamadas indirectas que también necesitan de  un CPI mayor.
  • Compilador: afecta directamente a la calidad del binario generado, nuevamente afectando al recuento de instrucciones y CPI. La eficiencia de un compilador se ha vuelto uno de los puntos más críticos, pudiendo afectar en gran medida a rendimiento. Además, se debería prestar atención a hacer los casos más comunes más rápidos, frente a tratar de optimizar casos que se producen rara vez. Por otro lado, para aprovechar mejor el paralelismo, el compilador debe generar código que sea capaz de ello, de lo contrario, los avances de hardware no servirían de nada. En ocasiones se puede caer en el problema de generar tareas dispares en tiempo, haciendo que unas partes estén muy ocupadas y no otras (balanceo de la carga), o que el tiempo de comunicación entre procesos paralelos se incremente.
  • ISA: afecta al recuento de instrucciones, a la velocidad de reloj, y al IPC. Mientras más simples y reducidas sea el repertorio de instrucciones, mejor IPC. Además, si se han diseñado adecuadamente, no se necesitarán tantas para implementar un mismo algoritmo, como le ocurre a ARM y RISC-V frente a las pesadas x86. Además, si son más sencillas, se necesitará un hardware menos complejo que pueda escalar más en frecuencia de reloj. Es más, los repertorios como ARM y RISC-V generan programas binarios que son entre un 25 y un 30% más pequeños que los x86, lo que también contribuye a la tasa de aciertos en la caché de instrucciones.
  • Microarquitectura: es la implementación para poder ejecutar la ISA o arquitectura. Mientras más eficiente y poderoso sea el diseño, mejor manejará el repertorio de instrucciones y más instrucciones podrá ejecutar por ciclo de reloj. Esto se consigue mediante técnicas de pipeline, superescalar, multithreading, ejecución fuera de orden, cache (aumentar la tasa de aciertos), predicción de saltos o ejecución especulativa, etc. En definitiva, mejorar el paralelismo y la forma en la que se procesan las instrucciones.
  • Latencia de memoria: como la CPU está constantemente accediendo a memoria, mejorar el ancho de banda y reducir la latencia es otro punto crítico.

Isaac

Apasionado de la computación y la tecnología en general. Siempre intentando desaprender para apreHender.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Si continuas utilizando este sitio aceptas el uso de cookies. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar