Danila (Dayfing)
Volver a publicaciones
3582 palabras18 min

Hardware para LLM en local en 2026: VRAM, ancho de banda de memoria, cuantización

Para ejecutar un modelo de lenguaje open-weight en local, el dispositivo que hace los cálculos necesita suficiente memoria rápida para tres cosas: los pesos cuantizados, la caché KV correspondiente a tu longitud de contexto y al número de peticiones simultáneas, y un margen para el entorno de ejecución. La capacidad decide qué modelos caben, el ancho de banda de memoria decide lo rápido que generan texto y la potencia de cálculo decide lo rápido que leen prompts largos. Como regla general, una GPU de 16 GB ejecuta bien modelos de clase 8B, entre 24 y 32 GB cubren modelos de clase 32B en 4 bits, y los modelos de clase 70B necesitan unos 48 GB o más: una tarjeta de estación de trabajo, dos GPU o un equipo con memoria unificada.

La fórmula de la memoria

Todo dimensionamiento parte de una sola suma:

memory ≈ weights + KV cache + runtime overhead

weights  = parameters × bits per weight / 8
KV cache = 2 × layers × kv_heads × head_dim × bytes per element × tokens in flight

Un modelo de 70.600 millones de parámetros necesita unos 141 GB para los pesos en 16 bits y unos 42 GB con 4,8 bits por peso.

La caché KV guarda las claves y los valores de atención de cada token que el modelo tiene en contexto, así que crece con cada token del prompt y de la respuesta. El factor 2 cubre claves y valores, y el resto de términos sale del config.json del modelo: num_hidden_layers, num_key_value_heads y head_dim. La mayoría de los modelos actuales usan grouped-query attention, con muchas menos cabezas KV que cabezas de consulta.

La sobrecarga del entorno de ejecución incluye el contexto de CUDA, ROCm o Metal y los búferes de cálculo. Reserva entre 1 y 2 GiB por dispositivo para llama.cpp, cuyo ajuste automático deja por defecto un margen de 1024 MiB por dispositivo, y más para servidores que reservan memoria por adelantado para lotes grandes. En memoria unificada, deja también sitio para el sistema operativo.

La caché KV crece con el contexto y la concurrencia

El coste por token se deduce directamente de los archivos de configuración:

Llama 3.1 8B:   2 × 32 layers × 8 kv_heads × 128 head_dim × 2 bytes = 128 KiB per token
Qwen3-32B:      2 × 64 layers × 8 kv_heads × 128 head_dim × 2 bytes = 256 KiB per token
Llama 3.3 70B:  2 × 80 layers × 8 kv_heads × 128 head_dim × 2 bytes = 320 KiB per token

Con 32.768 tokens son 4, 8 y 10 GiB con una caché de 16 bits. Con 131.072 tokens, la caché del modelo 70B llega a 40 GiB, lo mismo que sus pesos en 4 bits.

La concurrencia multiplica la caché: cuatro usuarios con conversaciones de 16K tokens ocupan lo mismo que una sola conversación de 64K. vLLM crea un pool KV con la memoria que queda tras cargar los pesos, y llama-server reparte un único presupuesto de contexto (-c) entre sus slots (--parallel). La guía de servidores de inferencia de LLM en local explica cómo gestiona cada servidor ese pool.

Hay dos palancas para reducir la caché. Una caché de 8 bits, -ctk q8_0 -ctv q8_0 en llama.cpp o --kv-cache-dtype fp8 en vLLM, la reduce aproximadamente a la mitad, y limitar el contexto a lo que la aplicación usa de verdad no cuesta nada. Las capas de ventana deslizante, la atención híbrida y el multi-head latent attention guardan menos por token, así que revisa el tamaño del búfer KV que llama.cpp muestra al cargar el modelo.

Ejemplos para modelos 8B, 32B y 70B

La documentación de cuantización de llama.cpp recoge los bits por peso medidos en Llama 3.1 8B: Q8_0 8,50, Q6_K 6,56, Q5_K_M 5,70, Q4_K_M 4,89, IQ4_XS 4,46 y Q3_K_M 4,00. Los modelos más grandes quedan algo por debajo: los archivos Q4_K_M publicados de Qwen3-32B y Llama 3.3 70B salen a unos 4,8. Este script aplica la fórmula con un contexto de 32K y 1,5 GiB de sobrecarga:

GiB = 2**30

def weights_gib(params, bits_per_weight):
    return params * bits_per_weight / 8 / GiB

def kv_gib(layers, kv_heads, head_dim, tokens, bytes_per_elem=2):
    return 2 * layers * kv_heads * head_dim * bytes_per_elem * tokens / GiB

models = {
    "Llama 3.1 8B": (8.03e9, 32),
    "Qwen3-32B": (32.76e9, 64),
    "Llama 3.3 70B": (70.55e9, 80),
}

for name, (params, layers) in models.items():
    kv = kv_gib(layers, 8, 128, 32768)
    for quant, bpw in (("BF16", 16.0), ("Q8_0", 8.5), ("Q4_K_M", 4.85)):
        w = weights_gib(params, bpw)
        print(f"{name:14} {quant:7} weights {w:6.1f} GiB  KV@32K {kv:5.1f} GiB  total {w + kv + 1.5:6.1f} GiB")
Llama 3.1 8B   BF16    weights   15.0 GiB  KV@32K   4.0 GiB  total   20.5 GiB
Llama 3.1 8B   Q8_0    weights    7.9 GiB  KV@32K   4.0 GiB  total   13.4 GiB
Llama 3.1 8B   Q4_K_M  weights    4.5 GiB  KV@32K   4.0 GiB  total   10.0 GiB
Qwen3-32B      BF16    weights   61.0 GiB  KV@32K   8.0 GiB  total   70.5 GiB
Qwen3-32B      Q8_0    weights   32.4 GiB  KV@32K   8.0 GiB  total   41.9 GiB
Qwen3-32B      Q4_K_M  weights   18.5 GiB  KV@32K   8.0 GiB  total   28.0 GiB
Llama 3.3 70B  BF16    weights  131.4 GiB  KV@32K  10.0 GiB  total  142.9 GiB
Llama 3.3 70B  Q8_0    weights   69.8 GiB  KV@32K  10.0 GiB  total   81.3 GiB
Llama 3.3 70B  Q4_K_M  weights   39.8 GiB  KV@32K  10.0 GiB  total   51.3 GiB

El modelo 8B cabe en una tarjeta de 12 GB en Q4_K_M y en una de 16 GB en Q8_0, así que en 16 GB no hay motivo de capacidad para bajar de Q6_K. El modelo 32B en Q4_K_M necesita una tarjeta de 32 GB para una caché completa de 32K; en 24 GB cabe con 16K de contexto y una caché de 8 bits, ocupando unos 22 GiB. El modelo 70B en Q4_K_M necesita unos 51 GiB: dos GPU de 32 GB, una tarjeta de estación de trabajo de 72 o 96 GB, o 64 GB o más de memoria unificada. Una tarjeta de 48 GB lo ejecuta con unos 8K de contexto, y Q8_0 exige una tarjeta de 96 GB o 128 GB de memoria unificada.

Formatos de cuantización y lo que cuestan

La cuantización guarda los pesos con menos bits más factores de escala por bloque. Ahorra memoria y acelera la generación, pero añade error.

K-quants e I-quants en GGUF

GGUF es el formato de archivo de llama.cpp, que también usan Ollama y LM Studio. Los K-quants como Q4_K_M y Q6_K cuantizan los pesos por bloques y mantienen los tensores sensibles en un tipo más preciso. Los I-quants como IQ4_XS empaquetan de forma más agresiva. Ambos mejoran con una matriz de importancia (imatrix) calculada sobre texto de calibración, y la documentación de llama.cpp mide su pérdida con la perplejidad y la divergencia de Kullback-Leibler. GGUF funciona en CUDA, ROCm, Vulkan, Metal y CPU, lo que lo convierte en la opción más portable.

8 bits y FP8

Q8_0 es el tipo GGUF de 8 bits. En servidores con GPU, el formato habitual de 8 bits es FP8. Según la documentación de FP8 de vLLM, el cálculo en FP8 requiere compute capability de NVIDIA 8.9 o superior (Ada Lovelace, Hopper, Blackwell), las GPU más antiguas recurren a núcleos W8A16 solo de pesos, y FP8 reduce a la mitad la memoria del modelo con hasta 1,6 veces más rendimiento y un impacto mínimo en la precisión.

AWQ, GPTQ y coma flotante de 4 bits

AWQ y GPTQ son métodos de 4 bits solo de pesos para servidores con GPU como vLLM y SGLang. Calibran escalas para grupos de pesos, mantienen las activaciones en 16 bits, y muchos autores de modelos publican directamente estas versiones, por ejemplo Qwen/Qwen3-32B-AWQ. Las GPU Blackwell añaden cálculo FP4 nativo, y los modelos gpt-oss de OpenAI guardan los pesos de sus expertos en MXFP4.

Cuánta calidad pierdes

Los formatos de 8 bits suelen ser difíciles de distinguir de BF16. Q6_K y Q5_K_M añaden un aumento de perplejidad pequeño pero medible y son una opción segura si la memoria lo permite. Los 4 bits son el compromiso habitual: la pérdida es medible y se nota sobre todo donde importan los errores pequeños, como el código, las matemáticas y la recuperación exacta de datos en contextos largos. Por debajo de 4 bits el error crece rápido, y los modelos pequeños sufren más que los grandes. Un modelo más grande en 4 bits suele superar a uno más pequeño en 8 bits con la misma memoria, pero compruébalo con tus propias tareas, como describe la guía de evaluación de agentes de IA.

El ancho de banda fija la velocidad de generación y el cálculo la del prompt

Generar un token con un modelo denso lee cada peso una vez, más la caché KV del contexto actual. Con un lote de tamaño 1, el movimiento de datos domina, así que el techo es sencillo:

decode tokens/s ≤ memory bandwidth / bytes read per token
bytes read per token ≈ weight bytes (dense) or active-expert bytes (MoE) + KV cache bytes at current depth

El archivo Llama 3.3 70B Q4_K_M ocupa 42,5 GB, así que el techo es de unos 42 tokens por segundo con 1792 GB/s, 14 con 614 GB/s y 6 con 256 GB/s. El archivo 8B Q4_K_M (4,9 GB) llega a unos 91 tokens por segundo con 448 GB/s. Los entornos reales quedan por debajo de estos techos y se ralentizan a medida que crece el contexto: a 32K, la caché del modelo 70B añade unos 10,7 GB de lectura por token.

La tabla de cuantización de llama.cpp muestra el patrón en una sola máquina con Llama 3.1 8B: la generación sube de unos 29 tokens por segundo en F16 a 51 en Q8_0 y 72 en Q4_K_M, mientras que el procesamiento del prompt se mantiene entre unos 700 y 920 tokens por segundo en todos los tipos.

El procesamiento del prompt trabaja con lotes de cientos de tokens, así que cada lectura de pesos sirve a muchos tokens y el límite pasa a ser el rendimiento matricial. El trabajo es de unas 2 × parameters × prompt tokens operaciones, alrededor de 5 × 10^14 para un prompt de 8000 tokens en un modelo 32B. Eso fija el tiempo hasta el primer token en retrieval-augmented generation, donde los prompts llevan fragmentos recuperados como en el diseño de búsqueda híbrida con pgvector, y en los agentes de código que envían archivos grandes. Mira ambas especificaciones: NVIDIA DGX Spark tiene un techo de generación modesto con 273 GB/s, pero NVIDIA atribuye a su chip GB10 hasta 1 PFLOP de cálculo FP4 disperso.

El batching atiende muchas secuencias con cada lectura de pesos, así que el rendimiento de un servidor sigue subiendo hasta que se agotan el cálculo o la caché. Los bucles de agentes dependen en cambio de la latencia de una sola petición, porque cada paso espera a la llamada anterior, como explica la guía de arquitectura de agentes de IA en producción.

Los modelos mixture-of-experts (MoE) separan ambas restricciones: la memoria sigue al total de parámetros y la velocidad de generación a los parámetros activos. gpt-oss-120b tiene 117.000 millones de parámetros con 5.100 millones activos, y su ficha de modelo indica que cabe en una sola GPU de 80 GB; su archivo MXFP4 GGUF ocupa 63,4 GB. gpt-oss-20b funciona dentro de 16 GB. Por eso siguen siendo útiles los equipos con mucha capacidad y un ancho de banda moderado.

Opciones de hardware según capacidad

GPU NVIDIA por clase de VRAM

Las GPU NVIDIA tienen el soporte más amplio de entornos de ejecución, porque vLLM, SGLang, TensorRT-LLM y llama.cpp tratan CUDA como plataforma de referencia. Compara primero la capacidad y después el ancho de banda dentro de cada clase: las tarjetas GeForce de 16 GB ejecutan los mismos modelos, pero la RTX 5080 tiene más del doble de ancho de banda que la RTX 5060 Ti. La RTX PRO 6000 Blackwell aloja un modelo 70B en 8 bits en una sola tarjeta. Las tarjetas GeForce RTX 50 no admiten NVLink, así que el tráfico entre varias GPU pasa por PCIe.

Memoria unificada: Apple Silicon, Ryzen AI Max, DGX Spark

Los sistemas con memoria unificada dan a la CPU y a la GPU un único pool LPDDR: mucha más memoria para el modelo que las GPU de consumo, con menos ancho de banda que una tarjeta GDDR7 rápida, salvo en el chip de Apple de gama más alta. En el Mac Studio, Apple ofrece el M5 Ultra desde 96 GB, anuncia la configuración de 512 GB para finales de octubre y admite agrupar varias unidades mediante Thunderbolt 5 con RDMA; entre los entornos de ejecución están llama.cpp sobre Metal y MLX. El Ryzen AI Max+ 395 de AMD usa una interfaz LPDDR5x-8000 de 256 bits, lo que da 256 GB/s, y el Ryzen AI Max+ PRO 495 pasa a LPDDR5x-8533, con equipos OEM anunciados para el tercer trimestre de 2026; llama.cpp funciona en ambos mediante ROCm o Vulkan. NVIDIA DGX Spark ejecuta la pila CUDA y tiene un puerto ConnectX-7 de 200 Gbps para conectar varias unidades.

Según la fórmula del techo, estos equipos ejecutan modelos densos 70B a velocidades de unos pocos tokens a unas pocas decenas por segundo, y los modelos MoE mucho más rápido. Sus GPU trabajan con un presupuesto de potencia muy inferior al de una tarjeta de 575 W, así que mide el tiempo hasta el primer token con tus prompts reales.

Plataforma Memoria para el modelo Ancho de banda Potencia Modelo denso con 32K de contexto
GeForce RTX 5060 Ti 16 GB 16 GB GDDR7 448 GB/s 180 W 8B en Q8_0
GeForce RTX 5070 Ti / 5080 16 GB GDDR7 896 / 960 GB/s 300 / 360 W 8B en Q8_0
GeForce RTX 5090 32 GB GDDR7 1792 GB/s 575 W 32B en Q4_K_M
RTX PRO 4000 / 4500 Blackwell 24 / 32 GB GDDR7 ECC 672 / 896 GB/s 145 / 200 W 32B en 4 bits
RTX PRO 5000 Blackwell 48 o 72 GB GDDR7 ECC 1344 GB/s 300 W 32B en Q8_0, 70B en Q4_K_M con 72 GB
RTX PRO 6000 Blackwell 96 GB GDDR7 ECC 1792 GB/s 600 W o 300 W (Max-Q) 70B en Q8_0
DGX Spark 128 GB LPDDR5x 273 GB/s fuente de 240 W 70B en Q8_0
Ryzen AI Max+ 395 128 GB, hasta 96 GB para gráficos 256 GB/s 45 a 120 W 70B en Q6_K
Ryzen AI Max+ PRO 495 192 GB, hasta 160 GB para gráficos unos 273 GB/s 45 a 120 W 70B en Q8_0
Mac Studio, M5 Max hasta 128 GB hasta 614 GB/s 480 W máximo del sistema 70B en Q8_0
Mac Studio, M5 Ultra hasta 512 GB 1,2 TB/s 480 W máximo del sistema 70B en BF16

La última columna sale de los ejemplos anteriores para un solo usuario. La tabla describe capacidades, no la relación calidad-precio.

Varias GPU y descarga en la CPU

Dos GPU duplican la capacidad, pero la velocidad depende de cómo se reparta el modelo. Con el reparto por capas, el modo por defecto de llama.cpp, cada GPU guarda un rango de capas y su caché KV, y con lote 1 las GPU trabajan por turnos: más capacidad, misma velocidad de generación. Por cada token solo cruzan el PCIe activaciones pequeñas, así que enlaces x8 o incluso x4 bastan. Con paralelismo tensorial (--tensor-parallel-size 2 en vLLM), ambas GPU leen a la vez su parte de cada capa, lo que eleva el techo, pero cada capa se sincroniza por PCIe. El paralelismo tensorial de vLLM está pensado para GPU idénticas, y el número de GPU debe dividir el número de cabezas de atención del modelo.

La descarga en la CPU deja algunas capas en la RAM del sistema, donde las ejecuta el procesador. El tiempo por token pasa a ser una suma: bytes en la GPU divididos por el ancho de banda de la VRAM, más bytes en la CPU divididos por el ancho de banda de la RAM. La DDR5-6000 en doble canal da 96 GB/s teóricos (2 canales × 8 bytes × 6000 MT/s), y la guía de memoria DDR5 explica cómo se combinan canales y frecuencias. Un modelo 70B Q4_K_M con 24 GB en la GPU y 18,5 GB en RAM se queda por debajo de 5 tokens por segundo. La descarga resuelve la capacidad, no la velocidad.

Los modelos MoE se descargan mucho mejor. --cpu-moe y --n-cpu-moe N mantienen los pesos de los expertos en RAM mientras la atención y la caché KV siguen en la GPU, y solo se leen los expertos activos en cada token. Las versiones recientes de llama.cpp ajustan las capas automáticamente cuando -ngl no está definido (--fit está activado por defecto); fíjalo de forma explícita si necesitas resultados reproducibles. Los comandos muestran un modelo denso descargado en parte, un modelo MoE con sus expertos en RAM y un reparto por capas inclinado hacia la GPU más grande:

llama-server -m Llama-3.3-70B-Instruct-Q4_K_M.gguf -c 16384 -ngl 48 -fa on

llama-server -hf ggml-org/gpt-oss-120b-GGUF -c 32768 -ngl all --n-cpu-moe 24 -fa on

llama-server -m Qwen_Qwen3-32B-Q8_0.gguf -c 32768 -ngl all --split-mode layer --tensor-split 3,2

Alimentación, refrigeración, líneas PCIe y RAM del sistema

Para la GeForce RTX 5090, NVIDIA indica 575 W de potencia gráfica y 1000 W de potencia de sistema requerida. La edición Max-Q de la RTX PRO 6000, de 300 W, mantiene la misma memoria que el modelo de 600 W, lo que importa si se montan varias tarjetas en un mismo chasis. Como la generación espera a la memoria, prueba un límite más bajo con nvidia-smi -pl y quédate con el valor en el que la velocidad de generación apenas cambia.

La inferencia es una carga sostenida, y dos tarjetas con refrigeración abierta en ranuras contiguas se lanzan aire caliente entre sí. Comprueba frecuencias, temperatura y potencia durante una prueba de 30 minutos.

Las tarjetas GeForce RTX 50 y RTX PRO Blackwell usan PCIe 5.0 x16. Las plataformas de sobremesa de consumo suelen ofrecer un enlace gráfico x16, que algunas placas dividen en x8/x8, y una ranura conectada al chipset suele funcionar en x4. El reparto por capas lo tolera; el paralelismo tensorial y la carga de modelos prefieren x8 o más, algo que ofrecen las plataformas de estación de trabajo. La generación de enlace que se muestra puede bajar mientras la GPU está en reposo, así que compruébala con carga.

Ten al menos tanta RAM del sistema como el archivo de modelo más grande que cargues, más espacio para el sistema operativo, y mucha más si descargas capas. Los archivos de modelo van de unos 5 GB a bastante más de 100 GB, así que una unidad rápida acorta los tiempos de carga; la guía de compra de SSD NVMe cubre ese caso.

nvidia-smi --query-gpu=name,pcie.link.gen.current,pcie.link.width.current,power.draw,memory.used --format=csv -l 1

nvidia-smi dmon -s pucvmt -d 1

sudo nvidia-smi -pl 450

Mide tu propio rendimiento

Las cifras publicadas rara vez coinciden con tu archivo de modelo, tu contexto, tu controlador y tu versión del entorno de ejecución, así que mide por tu cuenta y compara con la fórmula del techo. En llama-bench, -p fija la longitud del prompt, -n los tokens generados y -d rellena la caché KV hasta una profundidad dada, lo que muestra cómo cae la velocidad a medida que crece la conversación. El segundo comando compara una caché de 16 bits con una de 8 bits:

llama-bench -m Qwen_Qwen3-32B-Q4_K_M.gguf -p 512,4096 -n 128 -d 0,16384 -fa on -r 3 -o md

llama-bench -m Qwen_Qwen3-32B-Q4_K_M.gguf -p 4096 -n 128 -d 16384 -ctk f16,q8_0 -ctv f16,q8_0 -fa on

Después prueba la concurrencia. vllm bench serve funciona con endpoints compatibles con OpenAI e informa del tiempo hasta el primer token, el tiempo por token de salida, la latencia entre tokens y el rendimiento total:

vllm serve Qwen/Qwen3-32B-AWQ --max-model-len 32768

vllm bench serve --backend openai --base-url http://127.0.0.1:8000 --model Qwen/Qwen3-32B-AWQ --dataset-name random --random-input-len 4096 --random-output-len 256 --num-prompts 200 --max-concurrency 8

Divide la velocidad medida con un solo flujo entre el techo. Si la proporción es inusualmente baja, busca capas descargadas en la CPU sin que lo sepas, un enlace PCIe con anchura reducida, limitación térmica o de potencia, o un backend lento.

Lista de comprobación para dimensionar

  • Anota del config.json los parámetros, las capas, las cabezas KV y la dimensión de cabeza.
  • Elige la cuantización: 8 bits si cabe, luego Q6_K o Q5_K_M, luego 4 bits, y por debajo solo tras probar.
  • Fija el contexto y la concurrencia, calcula la caché KV y decide si una caché de 8 bits es aceptable.
  • Suma 1 a 2 GiB por dispositivo, más margen para el sistema operativo en memoria unificada.
  • Descarta las plataformas cuyo techo de generación quede por debajo de la velocidad que necesitas.
  • Para prompts largos de RAG o agentes de código, ten en cuenta el cálculo y mide el tiempo hasta el primer token.
  • En modelos MoE, dimensiona la memoria por el total de parámetros y la velocidad por los activos.
  • Revisa alimentación, refrigeración, líneas PCIe, RAM y almacenamiento antes de comprar una segunda GPU.
  • Mide, y reduce la distancia al techo antes de añadir hardware.

Más publicaciones