⏱️ Lectura: 16 min
Comprar una GPU de gama alta y descubrir que un modelo pesado corre mucho más lento de lo esperado es una sorpresa cara. El simulador llmspeed.dev busca resolver justamente eso: dejar sentir, antes de pagar por el hardware, qué determina la velocidad de LLM local según la GPU, la memoria unificada o la CPU que estés considerando.
📑 En este artículo
- TL;DR
- ¿Qué es la velocidad de LLM local?
- Por qué importa el rendimiento de un LLM local
- Cómo funciona la inferencia local de modelos de lenguaje
- Ejemplos prácticos y cómo empezar
- Casos de uso reales
- Errores comunes y buenas prácticas
- Comparativa de métodos para estimar el rendimiento de un LLM local
- Profundizando: el modelo roofline aplicado a inferencia
- Preguntas frecuentes
- ¿Qué mide exactamente la velocidad de LLM local?
- ¿Por qué una Mac con 512GB no siempre da más velocidad de inferencia local que una GPU con 24GB?
- ¿Qué significa el sufijo «A3B» en un modelo MoE y cómo afecta los tokens por segundo en local?
- ¿La cuantización empeora la calidad al acelerar la inferencia local de modelos de lenguaje?
- ¿Dónde puedo comparar el rendimiento de un LLM local antes de comprar el hardware?
- ¿Qué importa más para el rendimiento de un LLM local: los TFLOPS o el ancho de banda de memoria?
- Referencias
El proyecto es código abierto en GitHub y cruza decenas de GPUs, equipos Apple Silicon y configuraciones CPU-only con una lista de modelos abiertos populares. El número que aparece en pantalla depende de un puñado de factores técnicos que casi nunca se explican juntos, y son justamente los que cubre este artículo.
TL;DR
- El ancho de banda de memoria, no los TFLOPS, es el límite real de la velocidad de LLM local al generar tokens.
- Calculás tokens por segundo con una fórmula simple: ancho de banda entre bytes totales del modelo activo.
- Los modelos MoE con sufijo «A3B» activan solo una fracción de sus parámetros totales por token.
- La cuantización a 4 bits reduce a la mitad los bytes por parámetro frente a 8 bits y acelera la inferencia.
- Llmspeed.dev combina benchmarks de r/LocalLLaMA y localscore.ai para estimar velocidad antes de comprar hardware.
¿Qué es la velocidad de LLM local?
La velocidad de LLM local es la cantidad de tokens que un modelo de lenguaje genera por segundo al correr en el hardware propio del usuario, sea una GPU, una Mac o una CPU, en lugar de un servidor remoto. Depende del ancho de banda de memoria, el tamaño del modelo activo y la cuantización.
Esta velocidad no es una propiedad fija del modelo: el mismo archivo de pesos puede rendir 10 tokens por segundo en un equipo y 10 veces más en otro, según cómo se relacionen esos tres factores con el hardware específico.
Por qué importa el rendimiento de un LLM local
Un modelo que corre en tu propia máquina no depende de una API externa, no envía tus datos a un tercero y no tiene costo por token. Pero si la inferencia es demasiado lenta, esas ventajas se vuelven teóricas: nadie espera varios segundos entre cada palabra de un asistente de código.
El problema es que las especificaciones de una GPU o de una Mac no dicen directamente cuántos tokens por segundo vas a obtener con un modelo específico. Una tarjeta con más VRAM no siempre es más rápida: puede tener más capacidad pero menos ancho de banda que otra con menos memoria. Por eso herramientas como llmspeed intentan traducir specs crudas en una sensación concreta de velocidad antes de gastar el dinero.
Cómo funciona la inferencia local de modelos de lenguaje
El cuello de botella del ancho de banda
Generar un token nuevo obliga a leer, una vez más, todos los parámetros activos del modelo desde la memoria hacia los núcleos de cómputo. Ese recorrido se repite en cada paso de la generación, así que el techo de velocidad no lo pone la potencia de cómputo bruta sino cuántos bytes por segundo puede mover el bus de memoria.
Es la misma razón por la que una GPU dedicada con memoria GDDR6X suele superar a una Mac con memoria unificada en tokens por segundo puros, aunque la Mac tenga muchísima más capacidad. La capacidad decide qué modelo entra en memoria; el ancho de banda decide qué tan rápido corre una vez que entró.
flowchart LR
A["Pesos del modelo en VRAM"] --> B["Bus de memoria (GB/s)"]
B --> C["Nucleos de computo de la GPU"]
C --> D["Token generado"]
D --> A
Cuantización: menos bytes por parámetro
Cuantizar un modelo significa guardar cada parámetro con menos bits: de 16 bits (FP16) a 8 o 4 bits, por ejemplo. Menos bits por parámetro significa menos bytes que mover por el bus de memoria en cada token, así que la cuantización acelera la inferencia local incluso sin cambiar una sola línea del modelo.
La contrapartida es la precisión. Un modelo cuantizado a 4 bits pierde algo de calidad frente al mismo modelo en FP16, aunque en la práctica la diferencia suele ser menor de lo esperado para modelos grandes. El repositorio de llmspeed deja elegir el nivel de cuantización al simular cada combinación de modelo y hardware.
Denso vs MoE: cuántos parámetros se activan por token
Un modelo denso usa todos sus parámetros en cada token que genera. Un modelo Mixture of Experts (MoE) en cambio tiene un router que elige, para cada token, solo unos pocos expertos entre muchos disponibles. El modelo Qwen3 30B A3B de la lista de llmspeed ejemplifica la convención de nombres: 30B son los parámetros totales, y el sufijo A3B indica que solo 3.000 millones se activan por token.
Esa diferencia importa mucho para la velocidad. Un MoE de 30B con 3B activos se comporta, en bytes leídos por token, mucho más parecido a un modelo denso de 3B que a uno denso de 30B. Es la razón por la que modelos como GPT-OSS 120B pueden sentirse más rápidos de lo que su tamaño total sugiere.
flowchart TD
A["Parametros totales del modelo"] --> B{"Arquitectura"}
B -->|"Denso"| C["Todos los parametros activos en cada token"]
B -->|"MoE"| D["Router selecciona pocos expertos por token"]
D --> E["Solo una fraccion de parametros activos"]
Prefill vs decode
Procesar un prompt largo y generar la respuesta no son la misma tarea para el hardware. La fase de prefill (leer el prompt completo) es intensiva en cómputo paralelo y suele ser rápida en GPUs potentes. La fase de decode (generar cada token nuevo, uno a la vez) es la que sufre el cuello de botella de memoria descrito arriba.
sequenceDiagram
participant U as Usuario
participant M as Modelo local
U->>M: envia el prompt completo
M->>M: fase de prefill, procesa todo el prompt en paralelo
M-->>U: primer token
loop por cada token nuevo
M->>M: fase de decode, lee los parametros activos
M-->>U: siguiente token
end
El costo de memoria del contexto
A medida que una conversación crece, el modelo guarda un caché de claves y valores (KV-cache) con la información de cada token anterior para no recalcularla. Ese caché también vive en memoria y compite por el mismo ancho de banda que los parámetros del modelo.
Por eso la velocidad medida al principio de una conversación corta no se mantiene igual en una conversación larga: cuanto más crece el contexto, más memoria ocupa el KV-cache y menos ancho de banda queda disponible para leer los parámetros en cada paso de decodificación.
Ejemplos prácticos y cómo empezar
Antes de simular nada conviene entender la cuenta que hace el simulador por debajo. La fórmula más simple para estimar tokens por segundo en la fase de decode es dividir el ancho de banda de memoria disponible entre los bytes totales que hay que leer por cada token.
def tokens_por_segundo(bandwidth_gbps, params_billion, bytes_por_param=2):
bytes_totales = params_billion * 1e9 * bytes_por_param
return (bandwidth_gbps * 1e9) / bytes_totales
# Valores ilustrativos, no corresponden a una GPU real:
print(tokens_por_segundo(bandwidth_gbps=500, params_billion=8))
Esto imprime 31.25. Con un ancho de banda hipotético de 500 GB/s y un modelo denso de 8.000 millones de parámetros en FP16 (2 bytes por parámetro), el techo teórico de la fase de decode sería de poco más de 31 tokens por segundo.
El segundo paso es tener en cuenta cuántos parámetros se activan realmente. Los modelos MoE indican esa cifra en su propio nombre:
def parametros_activos(nombre_modelo):
# La convencion "AxB" indica cuantos miles de millones se activan por token
sufijo = nombre_modelo.split()[-1]
if sufijo.startswith("A") and sufijo.endswith("B"):
return float(sufijo[1:-1])
return None
print(parametros_activos("Qwen3 30B A3B"))
El resultado es 3.0. Pese a sus 30.000 millones de parámetros totales, Qwen3 30B A3B solo activa 3.000 millones por token, el mismo volumen que movería un modelo denso mucho más chico.
Combinando cuantización y arquitectura MoE, la cuenta cambia radicalmente:
def tokens_por_segundo_moe(bandwidth_gbps, activos_billion, bits_por_param=4):
bytes_por_param = bits_por_param / 8
bytes_totales = activos_billion * 1e9 * bytes_por_param
return (bandwidth_gbps * 1e9) / bytes_totales
# Qwen3 30B A3B cuantizado a 4 bits, mismo ancho de banda hipotetico de 500 GB/s:
print(tokens_por_segundo_moe(bandwidth_gbps=500, activos_billion=3))
El resultado sube a 333.33 tokens por segundo teóricos, diez veces más que el modelo denso del primer ejemplo, aunque ambos corran sobre el mismo ancho de banda hipotético. Esta es exactamente la clase de comparación que llmspeed automatiza para decenas de combinaciones reales de modelo y hardware.
Cómo correr el simulador en tu propia máquina
Llmspeed es, según su propio repositorio, código abierto. Para levantarlo localmente solo hace falta git y un servidor de archivos estáticos, y Python ya trae uno integrado:
git clone https://github.com/nicorobinreal/llmspeed.git
cd llmspeed
python3 -m http.server 8000
La terminal responde con algo como:
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Después abrís http://localhost:8000 en el navegador y ya podés elegir hardware y modelo desde la interfaz. En Windows, el comando equivalente en PowerShell o CMD es python -m http.server 8000, porque ahí el ejecutable se llama python y no python3.
Casos de uso reales
Un desarrollador que programa con asistentes de código corriendo localmente necesita que la fase de decode sea rápida: cada pausa de varios segundos entre tokens rompe el flujo de trabajo. Para ese caso importa el ancho de banda disponible para el modelo elegido, no la cantidad total de VRAM libre.
Un equipo de investigación que necesita cargar un modelo enorme para experimentar, aunque sea lento, prioriza la capacidad de memoria sobre la velocidad pura. Ahí entran máquinas con mucha memoria unificada, como Mac Studio M5 Ultra 512GB y Mac Studio M3 Ultra 512GB, que permiten cargar modelos que ninguna GPU de consumo puede ni siquiera alojar en VRAM.
Un presupuesto ajustado que solo puede pagar una CPU y RAM del sistema, sin GPU dedicada, es el tercer escenario. Llmspeed lista explícitamente una configuración CPU-only (Ryzen 9 9950X, 96GB DDR5) para ese caso, donde la expectativa realista de velocidad es mucho menor que en cualquier GPU de la lista.
Errores comunes y buenas prácticas
- Confundir capacidad con velocidad: tener 512GB de memoria unificada no implica tokens por segundo altos. La capacidad decide qué modelo entra; el ancho de banda decide qué tan rápido corre.
- Ignorar el crecimiento del contexto: a medida que una conversación se alarga, el KV-cache ocupa más memoria y compite por el mismo ancho de banda, así que la velocidad real baja con conversaciones largas.
- Mirar solo el primer token: la fase de prefill puede sentirse instantánea en una GPU potente mientras la fase de decode, la que determina la experiencia real de uso, sigue siendo lenta.
- Asumir que toda cifra es medida: llmspeed mezcla benchmarks reales de comunidades como r/LocalLLaMA y localscore.ai con estimaciones proyectadas a partir de specs, para las combinaciones que nadie probó todavía.
- Comparar cuantizaciones distintas sin aclararlo: un modelo en 4 bits y el mismo modelo en 16 bits no son comparables en velocidad ni en calidad sin fijar antes el nivel de cuantización.
Comparativa de métodos para estimar el rendimiento de un LLM local
| Método | Cuándo usarlo | Ventaja | Limitación |
|---|---|---|---|
| Simulador llmspeed.dev | Antes de comprar, sin acceso al hardware | Compara decenas de combinaciones modelo + hardware en segundos | Mezcla datos medidos con proyecciones por specs |
| Benchmarks de r/LocalLLaMA | Buscar reportes de usuarios con tu mismo hardware | Cifras de uso real, no solo teóricas | Dispersos y no siempre comparables entre configuraciones |
| localscore.ai | Verificar un benchmark estandarizado | Metodología consistente entre dispositivos | Cobertura limitada a lo que la comunidad sube |
| Cálculo manual (ancho de banda / bytes) | Estimar una combinación que nadie probó | Funciona para cualquier modelo y hardware con specs públicas | Ignora overhead real del software, como el KV-cache |
Profundizando: el modelo roofline aplicado a inferencia
La fórmula de ancho de banda dividido entre bytes es una simplificación del modelo roofline, una herramienta clásica de arquitectura de computadoras para predecir si una carga de trabajo está limitada por memoria o por cómputo. Para la fase de decode de un LLM, la intensidad aritmética (operaciones de cómputo por byte leído) es baja, así que casi siempre el techo lo pone la memoria y no la GPU.
Eso cambia con el tamaño del lote: si varias solicitudes comparten la misma pasada de lectura de parámetros, el costo de memoria se reparte entre más tokens generados a la vez, acercando la carga al límite de cómputo. Es la razón por la que un servidor que atiende a cientos de usuarios simultáneos puede ser mucho más eficiente por token que un solo usuario local generando de a uno.
La decodificación especulativa, que usa un modelo chico para proponer varios tokens y uno grande para verificarlos de una sola pasada, ataca el mismo cuello de botella desde otro ángulo. En lugar de acelerar la lectura de memoria, reduce cuántas veces hace falta repetirla.
💭 Clave: en inferencia local casi siempre conviene optimizar para ancho de banda de memoria antes que para TFLOPS, porque es el recurso que de verdad se agota primero.
📖 Resumen en Telegram: Ver resumen
Tu próximo paso: cloná el repositorio de llmspeed, corré python3 -m http.server 8000 y compará dos hardware de tu lista de compras con el mismo modelo para ver cuánto cambia la velocidad estimada.
Preguntas frecuentes
¿Qué mide exactamente la velocidad de LLM local?
Mide cuántos tokens por segundo genera un modelo de lenguaje corriendo en el hardware propio del usuario, separando la fase de prefill (procesar el prompt) de la fase de decode (generar cada token nuevo).
¿Por qué una Mac con 512GB no siempre da más velocidad de inferencia local que una GPU con 24GB?
Porque la capacidad de memoria y el ancho de banda son cosas distintas. La memoria unificada de una Mac permite cargar modelos enormes, pero suele tener menos ancho de banda que la memoria GDDR6X dedicada de una GPU, así que la GPU puede ganar en tokens por segundo con modelos que entren en sus 24GB.
¿Qué significa el sufijo «A3B» en un modelo MoE y cómo afecta los tokens por segundo en local?
Indica que, de los 30.000 millones de parámetros totales de un modelo como Qwen3 30B A3B, solo 3.000 millones se activan para generar cada token. Menos parámetros activos significa menos bytes que leer por token, así que estos modelos suelen rendir más tokens por segundo en local que un modelo denso del mismo tamaño total.
¿La cuantización empeora la calidad al acelerar la inferencia local de modelos de lenguaje?
Reduce la precisión numérica de cada parámetro, lo que puede afectar la calidad, pero en modelos grandes la diferencia entre 8 bits y 4 bits suele ser menor de lo que la gente espera. La ganancia en velocidad, en cambio, es directa: menos bytes por parámetro es menos tiempo de lectura en cada token.
¿Dónde puedo comparar el rendimiento de un LLM local antes de comprar el hardware?
Llmspeed.dev reúne una lista de GPUs, equipos Apple Silicon y configuraciones CPU-only cruzados con modelos abiertos populares, combinando benchmarks de comunidades como r/LocalLLaMA con proyecciones basadas en specs.
¿Qué importa más para el rendimiento de un LLM local: los TFLOPS o el ancho de banda de memoria?
Para la fase de decode, casi siempre el ancho de banda de memoria. Los TFLOPS importan más durante el prefill, cuando el modelo procesa el prompt completo en paralelo antes de empezar a generar.
Referencias
- llmspeed.dev: el simulador original en el que se basa este artículo, con benchmarks por hardware y por modelo.
- github.com/nicorobinreal/llmspeed: código fuente abierto del simulador y los datos de hardware y modelos que usa.
- localscore.ai: benchmark estandarizado de inferencia local que llmspeed usa como una de sus fuentes de datos medidos.
- r/LocalLLaMA: comunidad de Reddit que comparte benchmarks reales de modelos corriendo en hardware de consumo.
📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
Imagen destacada: Foto de Maxence Pira en Unsplash
¿Te sirvió? ¿Te dio otro error? Contalo abajo: las preguntas se responden y le sirven al siguiente que llegue.
Dejar un comentario
0 Comentarios