85.30 GFLOPS Single-Core FP32 Matrix Multiplication on AMD Zen 3: A Systematic Study of Cache Blocking, Register Blocking, FMA Chaining, and On-the-Fly Packing
Este artículo presenta un estudio de optimización sistemática sobre la microarquitectura AMD Zen 3 que logra 85.30 GFLOPS en la multiplicación de matrices FP32 de un solo núcleo mediante la evaluación de 28 configuraciones distintas de bloqueo de caché/registro, encadenamiento FMA y empaquetado sobre la marcha, identificando finalmente un diseño campeón que alcanza el 63.5% del rendimiento pico teórico al tiempo que introduce un modelo predictivo para optimizaciones futuras.
Artículo original bajo licencia CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Esta es una explicación generada por IA del artículo a continuación. No ha sido escrita ni avalada por los autores. Para mayor precisión técnica, consulte el artículo original. Leer descargo de responsabilidad completo
Imagina que estás intentando mover un enorme montón de arena (datos) de un lado a otro de un almacén gigante, pero tienes que hacerlo usando un pequeño y superrápido brazo robótico (el procesador). El objetivo es mezclar la arena con una fórmula especial (multiplicación de matrices) lo más rápido posible. Este artículo es un registro detallado del cuaderno de bitácora de un investigador, Lucas, intentando hacer que ese brazo robótico se mueva lo más rápido que humanamente sea posible en un tipo específico de chip informático llamado AMD Zen 3.
El Gran Objetivo: ¿Qué tan rápido es rápido?
El brazo robótico tiene una velocidad máxima teórica de 134.4 GFLOPS (eso son 134.4 mil millones de operaciones matemáticas por segundo). Piensa en esto como el límite de velocidad en una autopista. Lucas quería ver qué tan cerca podía llegar a ese límite de velocidad sin construir un coche nuevo, simplemente ajustando el motor.
Después de probar 28 estrategias de conducción diferentes, encontró una configuración "campeona" (llamada MX24) que alcanzó los 85.30 GFLOPS. Eso es aproximadamente el 63.5% de la velocidad máxima. No es un 100% perfecto, pero es un salto enorme desde la línea de salida, que era un método lento y torpe que funcionaba a solo 1.51 GFLOPS. De hecho, su mejor método fue 57 veces más rápido que la versión básica no optimizada.
La Estrategia Ganadora: La Danza de "4 Filas, Cadena de 4"
Para lograr esta velocidad, Lucas tuvo que descubrir cómo organizar la arena y los movimientos del robot. Aquí están los movimientos clave que descubrió:
1. El truco de empaquetado "sobre la marcha"
Imagina que la arena está almacenada en una cuadrícula donde tienes que caminar diagonalmente para agarrar el siguiente grano. Eso es lento y agotador. Lucas descubrió que copiar un pequeño trozo de la arena en una línea recta y ordenada justo antes de que el robot la necesite (llamado empaquetado sobre la marcha o on-the-fly packing) fue el movimiento mágico. Es como tener a un ayudante corriendo por delante y apilando los ladrillos en una fila perfecta para que el robot pueda simplemente agarrarlos uno tras otro sin tropezar. Esto superó al viejo método de simplemente agarrarlos tal como estaban, e incluso fue mejor que reorganizar todo el almacén de antemano.
2. El apilamiento de "4 Filas"
El robot tiene un número limitado de manos (registros) para sostener la arena mientras trabaja. Lucas probó sosteniendo 2 filas de arena, luego 4, luego 8.
- 2 Filas: Demasiado poco. El robot tenía que detenerse y buscar nueva arena con demasiada frecuencia.
- 8 Filas: ¡Demasiado! Sus manos estaban tan llenas que tenía que dejar caer arena al suelo (memoria) y recogerla de nuevo constantemente. Esto fue un desastre.
- 4 Filas: El punto ideal. Aunque el robot tuvo que dejar caer algunos granos al suelo y recogerlos de nuevo (un proceso llamado "derrame" o spilling), el trabajo extra valió la pena porque podía procesar más arena a la vez. Este único cambio hizo que el robot fuera un 59% más rápido que el método de 2 filas.
3. El ritmo de "Cadena de 4"
El brazo del robot tarda 4 segundos (ciclos) en terminar un solo movimiento matemático antes de poder empezar el siguiente sobre la misma pieza de arena. Si el robot hiciera un solo movimiento y esperara, estaría ocioso durante 3 segundos.
Lucas descubrió que si el robot sostenía 4 pilas diferentes de arena en sus manos y trabajaba en ellas en un bucle (Cadena-4), podía mantener el brazo moviéndose constantemente. Mientras una pila de arena se estaba "cocinando", él trabajaba en las otras. Esto encajaba perfectamente con el tiempo de cocción de 4 segundos del robot, manteniendo el motor zumbando a toda velocidad.
Lo que No Funcionó (La lista de "No lo hagas")
A veces, lo que crees que debería funcionar, en realidad lo empeora. Lucas probó algunas ideas populares y descubrió que eran terribles para este robot específico:
- El error del "Pre-fetch": La gente suele decirle a los robots que "miren hacia adelante" y agarren el siguiente grano de arena antes de que lo necesiten. Lucas probó esto, pero los ojos integrados del robot ya eran tan buenos viendo el patrón que los comandos adicionales de "mirar hacia adelante" solo estorbaron. Esto ralentizó al robot aproximadamente un 8%.
- El vertido "No Temporal": Existe un truco donde le dices al robot que vierta la arena directamente en el suelo sin ponerla en un contenedor primero. Esto funciona muy bien si solo estás tirando basura. Pero aquí, el robot tiene que mezclar la arena, lo que significa que tiene que recogerla de nuevo. Verterla directamente hizo que el robot tropezara con sus propios pies, desplomando su velocidad a unos patéticos 1.24 GFLOPS.
- La sobrecarga de "8 Filas": Como se mencionó, intentar sostener 8 filas de arena causó que el robot dejara caer tanta arena que pasaba más tiempo recogiéndola que moviéndola.
¿Qué tan seguros estamos?
El artículo tiene mucha confianza en estos números porque fueron medidos, no solo adivinados. Lucas ejecutó el código 15 veces para cada estrategia, descartó las ejecuciones más rápidas y más lentas (para evitar glitches extraños de la computadora) y promedió el resto. También verificó las matemáticas contra una versión simple y lenta para asegurarse de que la versión rápida no hiciera trampa.
Incluso construyó un modelo de "pre-filtro" matemático —una especie de bola de cristal— para predecir qué tan rápida sería una estrategia antes de ejecutarla realmente. Esta bola de cristal fue bastante buena, situándose dentro de un 11.3% de la velocidad real para la mayoría de las estrategias. Tendió a ser un poco conservadora, prediciendo que la mejor estrategia sería de 78.1 GFLOPS, pero cuando realmente la ejecutaron, alcanzó los 85.30 GFLOPS.
La Conclusión
Este artículo demuestra que no necesitas ser un mago escribiendo código en "lenguaje ensamblador" (la lengua nativa del robot) para obtener una velocidad increíble. Al usar herramientas estándar (intrínsecos de C++) y ajustar cuidadosamente los "pasos de baile" (bloqueo, encadenamiento y empaquetado), puedes lograr que tu computadora funcione al 63.5% de su velocidad máxima teórica.
¿La lección principal? No adivines. Lo que funciona para un tipo de robot (o chip de computadora) puede romper otro. Lucas probó 28 combinaciones diferentes para encontrar la que funcionaba, demostrando que, a veces, los trucos "obvios" (como mirar hacia adelante o verter directamente) son en realidad los movimientos equivocados.
¿Ahogado en artículos de tu campo?
Recibe resúmenes diarios de los artículos más novedosos que coincidan con tus palabras clave de investigación — con resúmenes técnicos, en tu idioma.