Cómo reducir el consumo de VRAM al ejecutar modelos de IA en local

Ejecutar un modelo de lenguaje en local obliga a mirar la memoria de la GPU casi con la misma atención que el número de parámetros. La VRAM no se consume únicamente por los pesos del modelo: también entran en juego la caché KV, el tamaño del contexto, el batch, las activaciones, el formato de cuantización y el motor de inferencia. Técnicas como INT4, FlashAttention, CPU offload o una buena gestión de la caché pueden permitir que un modelo entre en una GPU mucho más modesta, pero algunas cifras que circulan habitualmente simplifican demasiado lo que ocurre realmente.

Las claves para ahorrar VRAM con LLM locales en 20 segundos

  • Cuantizar a 8 o 4 bits reduce de forma considerable la memoria ocupada por los pesos.
  • En contextos largos, la KV cache puede convertirse en uno de los principales consumidores de VRAM.
  • FlashAttention reduce memoria intermedia, pero no existe un ahorro fijo del 30 % para cualquier modelo.
  • CPU offload permite ejecutar modelos mayores que la VRAM disponible, a costa de rendimiento.
  • Podar capas es posible, pero no debería considerarse una optimización genérica sin medir la pérdida de calidad.

La regla básica para estimar la memoria de los pesos es relativamente sencilla. Un modelo de 7.000 millones de parámetros en FP16 necesita teóricamente unos 14 GB solo para almacenar los pesos. En INT8 esa cifra se acerca a 7 GB y en 4 bits, antes de contar metadatos y otros elementos, a unos 3,5 GB.

Eso explica por qué cuantizar suele ser la primera medida cuando un modelo no cabe en la GPU.

Pero la memoria real siempre será superior a ese cálculo. Los formatos cuantizados incorporan escalas, bloques y metadatos; el runtime reserva memoria adicional y, cuando empieza la inferencia, aparece la caché necesaria para mantener el contexto de la conversación.

Por eso afirmar que un modelo de 13B «ocupa entre 4 y 6 GB» simplemente por utilizar INT4 puede ser demasiado optimista. Solo sus pesos teóricos a cuatro bits ya rondan los 6,5 GB, antes de añadir overhead y memoria de ejecución.

Cuantización: la forma más directa de meter modelos grandes en GPU pequeñas

La cuantización reduce la precisión con la que se representan los pesos del modelo.

En lugar de mantenerlos en FP16 o BF16, pueden utilizarse formatos de 8, 6, 5, 4 bits e incluso inferiores en determinados motores.

llama.cpp, por ejemplo, soporta actualmente cuantizaciones desde 1,5 hasta 8 bits y utiliza GGUF como formato habitual para almacenar y ejecutar modelos locales. El propio proyecto advierte de que reducir la precisión disminuye el tamaño y puede acelerar la inferencia, pero puede introducir pérdida de calidad.

Hugging Face ofrece otro camino mediante bitsandbytes. Su implementación LLM.int8() reduce aproximadamente a la mitad la memoria necesaria para los pesos frente a 16 bits, mientras las variantes de 4 bits permiten comprimir todavía más el modelo.

En vLLM existen actualmente múltiples alternativas: GPTQ, BitsAndBytes, AWQ, FP8, INT8 e INT4, entre otras.

La elección depende del hardware y del caso de uso.

Precisión aproximadaMemoria teórica para 7BMemoria teórica para 13B
FP3228 GB52 GB
FP16/BF1614 GB26 GB
INT87 GB13 GB
INT43,5 GB6,5 GB

Son cálculos únicamente sobre parámetros. No representan la VRAM total necesaria para ejecutar el modelo.

Además, no todas las cuantizaciones ofrecen la misma calidad. GPTQ, AWQ, GGUF Q4_K_M, NF4 o FP8 siguen estrategias diferentes y pueden comportarse de forma distinta dependiendo de la arquitectura.

La recomendación práctica no debería ser simplemente «usar INT4», sino probar qué cuantización mantiene una calidad suficiente para la tarea concreta.

La KV cache puede comerse la VRAM que se ahorró con los pesos

En modelos utilizados para conversaciones largas aparece otro consumidor importante: la KV cache.

Un transformer evita recalcular desde cero toda la atención de los tokens anteriores almacenando las claves y valores generados en cada capa.

Cuanto mayor es el contexto, mayor es esa caché.

Esto explica una situación habitual: un modelo entra perfectamente en una GPU al arrancar, pero aparece un error de memoria cuando se aumenta mucho el contexto o se atienden varias peticiones simultáneamente.

vLLM permite incluso definir explícitamente cuántos bytes de memoria de cada GPU se reservan a esta caché mediante kv_cache_memory_bytes, porque puede representar una fracción considerable de la VRAM disponible.

La consecuencia es que optimizar modelos locales exige pensar en dos bloques diferentes:

pesos + memoria de inferencia.

Un modelo de 4 bits con 128.000 tokens de contexto puede terminar necesitando más VRAM que el mismo modelo en una cuantización algo superior con una ventana de contexto mucho menor.

Reducir max_model_len, utilizar contextos razonables y evitar guardar miles de tokens innecesarios puede proporcionar más margen que algunas optimizaciones mucho más sofisticadas.

vLLM también soporta KV cache cuantizada, una técnica destinada precisamente a reducir la memoria utilizada para mantener estos estados durante contextos largos.

FlashAttention ayuda, pero no existe un 30 % universal

FlashAttention suele aparecer en cualquier lista de técnicas para ahorrar VRAM.

Tiene sentido.

La atención convencional puede crear grandes matrices intermedias cuyo tamaño aumenta rápidamente con la longitud de la secuencia. Las implementaciones FlashAttention reorganizan el cálculo para reducir movimientos de memoria y evitar almacenar determinados resultados intermedios completos.

PyTorch incorpora actualmente kernels optimizados para scaled dot product attention y puede seleccionar automáticamente FlashAttention o implementaciones de atención eficiente en memoria cuando el hardware y los parámetros son compatibles.

El beneficio puede ser importante, sobre todo con secuencias largas.

Lo que no resulta correcto es presentar una cifra como «30 % menos VRAM» como si fuera constante.

El ahorro depende del modelo, longitud de contexto, batch, implementación, tipo de GPU y parte de la memoria total que corresponda realmente al cálculo de atención.

Si los pesos ocupan casi toda la VRAM, FlashAttention no va a reducir mágicamente ese espacio.

Su principal ventaja aparece en la memoria temporal del mecanismo de atención y en el rendimiento del procesamiento de secuencias largas.

Reducir el batch sí ahorra memoria, pero tampoco una cantidad fija

Otro consejo frecuente consiste en establecer:

batch size = 1

La lógica es correcta.

Procesar menos secuencias simultáneamente reduce activaciones y diferentes buffers de ejecución. Para una instalación doméstica en la que existe un único usuario, el batch pequeño suele ser perfectamente razonable.

Pero tampoco puede afirmarse que esto vaya a ahorrar siempre 2 o 4 GB.

En serving empresarial ocurre además lo contrario: reducir demasiado el batching puede desperdiciar capacidad de la GPU y disminuir considerablemente el número total de tokens procesados por segundo.

Motores como vLLM están diseñados precisamente para aprovechar el batching continuo y repartir eficientemente memoria entre diferentes solicitudes.

La elección cambia por tanto según la finalidad.

Para un chatbot local de una única persona:

latencia y VRAM disponible pueden tener prioridad.

Para una API utilizada por cientos de usuarios:

throughput y aprovechamiento de GPU pesan mucho más.

CPU offload funciona, pero PCIe se convierte en parte de la ecuación

Cuando el modelo sigue sin caber, existe otra posibilidad: dejar parte de sus pesos en la memoria RAM del sistema.

llama.cpp soporta inferencia híbrida CPU+GPU precisamente para ejecutar modelos superiores a la VRAM total disponible.

vLLM dispone también de cpu_offload_gb. La propia documentación lo describe como una forma de aumentar «virtualmente» la memoria de la GPU utilizando RAM del host. Un equipo con una GPU de 24 GB y 10 GB de offload podría, desde el punto de vista de capacidad, disponer de espacio suficiente para pesos que necesiten alrededor de 34 GB.

Pero hay una contrapartida importante.

Los pesos que no están en VRAM tienen que atravesar el enlace CPU-GPU durante la inferencia. En una GPU discreta, eso significa normalmente PCIe.

La penalización puede ser pequeña, grande o enorme dependiendo de cuánto se descargue, del ancho de banda disponible y del patrón de ejecución.

Por eso tampoco resulta fiable afirmar que el CPU offload sea simplemente «un 20-30 % más lento».

Con unas pocas capas fuera de GPU puede ser asumible. Si gran parte del modelo tiene que moverse continuamente, el rendimiento puede caer mucho más.

El offload es una excelente herramienta para hacer funcionar un modelo que de otro modo no arrancaría, pero no sustituye a disponer de suficiente memoria cuando se necesita alto rendimiento.

Podar capas es posible, pero cambia el modelo

Probablemente el consejo que más precaución requiere es eliminar las últimas capas de un modelo.

llama.cpp dispone incluso de una opción --prune-layers que permite hacerlo durante determinados procesos de preparación.

Eso demuestra que técnicamente es posible.

Pero eliminar dos o cuatro capas de un modelo de 13B no debería presentarse como un método seguro para convertirlo en un modelo de 8 GB «sin destruir el rendimiento».

Las capas forman parte de los pesos entrenados y eliminar algunas modifica la red.

La degradación puede variar enormemente dependiendo del modelo, qué capas se retiran y la tarea evaluada.

Esto es muy diferente de cuantizar.

En una cuantización, la arquitectura sigue siendo esencialmente la misma y se intenta representar sus parámetros utilizando menos bits. Con pruning estructural se modifica directamente la red.

Puede resultar útil en trabajos de investigación o cuando existe una evaluación específica detrás, pero para un usuario que únicamente quiere reducir VRAM suele ser preferible empezar por cuantización, contexto, KV cache y offload.

Hay otras optimizaciones más útiles antes de empezar a cortar el modelo

Para inferencia local, el orden práctico podría ser bastante diferente al que suele aparecer en infografías.

Primero conviene elegir un modelo cuyo tamaño tenga sentido para el hardware.

Después, una cuantización adecuada.

A continuación hay que controlar el contexto y la KV cache.

Solo después tiene sentido valorar offload, reparto entre varias GPU u otras técnicas.

llama.cpp, por ejemplo, permite dividir un modelo entre varias GPU mediante diferentes modos y especificar qué proporción carga cada dispositivo.

También puede ajustar automáticamente diferentes parámetros para intentar encajar el modelo dentro de la memoria disponible.

vLLM ofrece controles sobre el porcentaje de VRAM que puede utilizar cada instancia, con gpu_memory_utilization, cuyo valor predeterminado actual es 0,92.

En un servidor compartido resulta especialmente importante no configurar el runtime como si fuese el único proceso que utiliza la GPU.

La memoria unificada cambia las reglas en Apple Silicon

No todas las plataformas pueden analizarse únicamente en términos de VRAM.

Los Mac con Apple Silicon utilizan memoria unificada, compartida entre CPU y GPU. Un equipo con 64 GB no tiene una GPU convencional con 64 GB de VRAM dedicada, pero puede permitir ejecutar modelos que no entrarían en muchas tarjetas gráficas de consumo.

llama.cpp considera Apple Silicon una plataforma de primer nivel y dispone de optimizaciones específicas mediante ARM NEON, Accelerate y Metal.

La contrapartida está en el ancho de banda de memoria y rendimiento del procesador concreto.

Para determinados usos de inferencia local, tener mucha memoria disponible puede ser más importante que disponer de una GPU que alcance muchos TFLOPS pero solo incorpore 8 o 12 GB de VRAM.

La elección del hardware debería partir, por tanto, del modelo que se quiere ejecutar y no al revés.

Una GPU de 8 GB puede hacer mucho, pero no todo

Con cuantización de cuatro bits, una GPU de 8 GB puede ejecutar modelos que hace pocos años habrían parecido demasiado grandes para hardware doméstico.

Pero el margen es limitado.

Un 7B u 8B cuantizado entra con bastante comodidad en muchos escenarios. Un modelo de alrededor de 13B puede acercarse demasiado al límite dependiendo del formato, contexto y runtime.

Con 12 o 16 GB se abre una franja mucho más cómoda para modelos medianos.

24 GB, como los disponibles en determinadas GPU de gama alta, permiten ejecutar modelos considerablemente mayores y mantener contextos más generosos.

El cálculo básico de pesos ayuda a hacerse una idea inicial:

memoria aproximada de pesos =
parámetros × bits por parámetro / 8

Para 13.000 millones de parámetros a 4 bits:

13.000.000.000 × 4 / 8
≈ 6,5 GB

Y todavía faltaría añadir la memoria necesaria para ejecutar el modelo.

Por eso medir es mejor que memorizar reglas como «13B = 6 GB».

Para empresas, optimizar VRAM no es el objetivo final

En una estación de trabajo personal, conseguir que un LLM entre en una GPU puede ser el principal desafío.

En una empresa, la pregunta cambia.

Un modelo que funciona correctamente para una persona con batch=1 y CPU offload puede resultar económicamente desastroso cuando debe responder a cientos de usuarios.

Hay que medir tokens por segundo, latencia hasta el primer token, throughput, concurrencia, consumo energético y coste por solicitud.

También importa decidir si realmente hace falta el modelo más grande.

Un modelo más pequeño especializado, un sistema RAG correctamente construido o incluso una combinación de modelos puede ofrecer mejores costes y tiempos de respuesta que intentar ejecutar un LLM enorme para cualquier proceso.

Antes de comprar más GPU conviene optimizar la arquitectura.

Pero antes incluso de optimizar la arquitectura debería responderse otra pregunta: qué proceso empresarial se está intentando mejorar y qué nivel de modelo necesita realmente para hacerlo.

Ahí está la diferencia entre conseguir que una demo funcione y construir una plataforma de IA que tenga sentido mantener en producción.

Preguntas frecuentes

¿Cuánta VRAM necesita un modelo de 7B?

En FP16, únicamente los pesos requieren aproximadamente 14 GB. En 8 bits rondarían 7 GB y en 4 bits unos 3,5 GB teóricos, aunque la memoria real será superior por la KV cache, buffers y otros elementos del runtime.

¿Cuantizar un modelo reduce su calidad?

Puede hacerlo. La pérdida depende del método, el número de bits, la arquitectura y la tarea. Herramientas como llama.cpp, GPTQ, AWQ o bitsandbytes utilizan técnicas diferentes para intentar reducir esa degradación.

¿FlashAttention reduce siempre un 30 % la VRAM?

No. Puede reducir de forma importante la memoria utilizada durante el cálculo de atención, especialmente con contextos largos, pero el ahorro total depende del modelo y de la carga. No existe un porcentaje universal.

¿Es recomendable descargar parte del modelo a la CPU?

Es útil cuando el modelo no entra completamente en VRAM. Tanto llama.cpp como vLLM soportan esta estrategia, pero el intercambio continuo de datos entre CPU y GPU puede reducir el rendimiento, especialmente cuando se descarga una parte grande del modelo.

Scroll al inicio