---
title: "Palancas para gastar menos vatios por token: catálogo cuantificado para inferencia LLM"
url: https://blog.lo0.es/posts/palancas-eficiencia-energetica-inferencia/
markdown: https://blog.lo0.es/posts/palancas-eficiencia-energetica-inferencia/index.md
lang: es
date: 2026-06-16
lastmod: 2026-06-17
author: "José Manuel Román"
description: "Catálogo cuantificado de las palancas de eficiencia energética en inferencia LLM on-premise: cuantización FP8/INT4/AWQ reduce el J/token un 30–50%, power capping al 70% del TDP recorta la potencia un 30% con \u003c10% de pérdida de throughput, DVFS ahorra hasta un 45% en la fase de decode. Con tablas de impacto, fórmula de J/token, curva power cap vs throughput y herramientas OSS."
tags: ["energia","eficiencia","power-capping","cuantizacion","dvfs","zeus","j-por-token","serie-datos"]
translations:
  en: https://blog.lo0.es/en/posts/levers-fewer-watts-per-token-llm-inference/index.md
---

# Palancas para gastar menos vatios por token: catálogo cuantificado para inferencia LLM


> Notación: importes en **euros (N €)**, decimales con coma. No se usa el símbolo de dólar
> (en este sitio es delimitador de fórmula).

## TL;DR

Siete palancas independientes actúan sobre el numerador o el denominador de la identidad
\(\text{J/token} = \text{potencia (W)} / \text{throughput (tok/s)}\). Aplicadas en orden de
coste-beneficio: la **cuantización** (FP16→FP8) recorta el J/token un 30–50% sin cambiar hardware;
el **power capping** al 70% del TDP reduce la potencia un 30% con menos de un 10% de caída de
throughput en cargas memory-bound; el **DVFS** en fase decode ahorra un 22–45% adicional; el
**continuous batching** baja el J/token un 25–40% respecto a stacks sin optimizar; el **speculative
decoding** recorta hasta un 29% el J/token en batch bajo; el **prefix caching** elimina el
recompute de prefill para prompts repetidos; y el **scheduling a horas limpias** desplaza la
huella de carbono sin cambiar el consumo físico. Referencia de partida: un stack vLLM FP16 en H100
SXM (700 W TDP) con Llama-3 70B produce ~0,39 J/token bajo cargas batch realistas; un stack
sin optimizar (PyTorch baseline) parte de 2–6× más. Las palancas se apilan; el efecto combinado
puede llegar a un 73% de reducción respecto al baseline no optimizado
([arXiv 2504.17674](https://arxiv.org/pdf/2504.17674)).

---

## La identidad de referencia

$$\text{J/token} = \frac{\overline{P}\ [\text{W}]}{\text{throughput}\ [\text{tok/s}]}$$

donde \(\overline{P}\) es la potencia media sobre la ventana de medición (ver metodología en
[energía por token](https://blog.lo0.es/posts/energia-por-token-metodologia/index.md)). Las palancas actúan sobre uno
de los dos factores:

- **Reducen \(\overline{P}\)**: power capping, DVFS, scheduling a horas de baja intensidad.
- **Aumentan throughput** (denominador): cuantización, continuous batching, speculative decoding,
  prefix caching, chunked prefill, selección de modelo.
- **Ambos a la vez**: cuantización (menor footprint de pesos → mayor batch cabe en VRAM → mayor
  throughput a potencia similar o menor).

La fórmula expandida incluyendo el overhead de infraestructura:

$$\text{J/token}_{\text{efectivo}} = \frac{\overline{P}_{\text{GPU}} + \overline{P}_{\text{resto nodo}}}{\text{throughput}_{\text{tok/s}}} \times \text{PUE}$$

Para los cálculos de palancas se trabaja sobre \(\overline{P}_{\text{GPU}}\) por claridad; el
factor PUE (ver [energía por token](https://blog.lo0.es/posts/energia-por-token-metodologia/index.md)) amplifica o
atenúa el efecto de cada palanca de forma proporcional.

---

## Tabla maestra: palancas × impacto × coste × herramienta

| Palanca | Reducción J/token (%) | Efecto en latencia | Efecto en calidad | Herramienta OSS principal | Fuente |
|---|---|---|---|---|---|
| Cuantización FP16→FP8 | **30–50%** | −8–33% TPOT (mejora) | degradación <1% en benchmarks | vLLM, TRT-LLM, llm-compressor | arXiv 2504.17674, baseten.co |
| Cuantización FP16→INT4 (AWQ/GPTQ) | **45–60%** | mejora latencia (menor BW) | degradación 1–3% según modelo | AutoAWQ, llm-compressor, vLLM | arXiv 2504.17674 |
| Continuous batching vs estático | **25–40%** vs PyTorch | +5× throughput (mejora) | sin impacto | vLLM, TGI, TRT-LLM | arXiv 2504.17674, TokenPowerBench |
| Power capping 70% TDP | **20–30%** potencia | <10% throughput (decode) | sin impacto | nvidia-smi, DCGM, Zeus | arXiv 2604.11391, NERSC docs |
| DVFS decode-phase | **22–45%** en decode | 1–6% latencia total | sin impacto | nvidia-smi, GreenLLM, DVFS-GPT | arXiv 2501.08219, HAL 05190051 |
| Speculative decoding | **hasta 29%** (batch≤16) | TTFT mejora | sin impacto demostrable | vLLM, TRT-LLM | arXiv 2602.09113 |
| Prefix caching | **50–90%** en prefill reusable | TTFT −50–80% (prompts repetidos) | sin impacto | vLLM, SGLang | vLLM docs |
| Chunked prefill | ~10–15% en cargas mixtas | TTFT más estable | sin impacto | vLLM (SARATHI) | arXiv 2308.16369 |
| Selección SLM vs LLM denso | **60–80%** (modelo 7B vs 70B) | latencia baja | degradación variable por tarea | Ollama, vLLM, llama.cpp | arXiv 2504.17674 |
| Scheduling a horas limpias | 0% J/token, hasta −70% CO₂ | sin impacto en la carga | sin impacto | Kueue, Volcano, cron | ACM SLIT, arXiv 2507.09942 |

> Nota: los porcentajes son sobre el J/token efectivo de la carga, no sobre la potencia de placa
> en vacío. Los efectos se miden siempre en condiciones de igual calidad de salida (mismo modelo,
> mismo serving stack, misma distribución de prompts).

---

## Palanca 1: cuantización

### Mecánica

La cuantización reduce la precisión numérica de los pesos (y opcionalmente las activaciones),
lo que acorta el tiempo de lectura de pesos desde HBM por token generado. El decode es
memory-bandwidth-bound: el cuello es leer los pesos, no computar. Reducir la anchura de bits
libera ancho de banda para mayor throughput o permite meter más batch en VRAM.

| Formato | Bits/peso | Reducción BW vs FP32 | J/token vs FP16 | Herramienta |
|---|---|---|---|---|
| FP32 | 32 | 1× (referencia) | +100% (peor) | — |
| BF16/FP16 | 16 | 2× | referencia | vLLM nativo |
| FP8 (W8A8) | 8 | ~4× | **−30–50%** | vLLM, TRT-LLM, llm-compressor |
| INT4 AWQ (W4A16) | 4 | ~8× | **−45–60%** | AutoAWQ, llm-compressor |
| INT4 GPTQ (W4A16) | 4 | ~8× | **−40–55%** | AutoGPTQ, vLLM |

Datos concretos de referencia:

- Llama-3 405B en H100, FP16→FP8: −30% J/token medido; TPOT mejora un 33% (Baseten,
  [baseten.co/blog/33-faster-llm-inference-with-fp8-quantization](https://www.baseten.co/blog/33-faster-llm-inference-with-fp8-quantization/)).
- El stack vLLM+CUDA graphs vs PyTorch baseline: 2–6× más eficiente en J/token
  ([arXiv 2504.17674](https://arxiv.org/pdf/2504.17674)).
- Llama-65B en V100 FP16: 3–4 J/token. Llama-3 70B en H100 FP8: 0,39 J/token. Reducción
  combinada hardware+cuantización: ~90%
  ([MLCommons, arXiv 2504.17674](https://mlcommons.org/2025/09/mlperf-inference-v5-1-results/)).

### Coste de calidad

La cuantización FP8 con calibración produce degradación <1% en benchmarks estándar (MMLU,
HumanEval). INT4 AWQ puede producir 1–3% de degradación dependiendo del modelo y la tarea;
INT4 GPTQ sin calibración fina, hasta 2–5%. Se valida con [leaderboards de energía](https://blog.lo0.es/posts/leaderboards-energia-llm/index.md) y benchmarks de calidad propios.

### Herramientas OSS

```bash
# vLLM con FP8 (cuantización en tiempo de carga, H100/A100)
vllm serve meta-llama/Llama-3-70B-Instruct \
  --quantization fp8 \
  --dtype auto

# llm-compressor: cuantización offline a W4A16 (AWQ)
python -m llmcompressor.transformers.compression.helpers \
  --model meta-llama/Llama-3-70B-Instruct \
  --recipe w4a16_awq.yaml \
  --output-dir llama-70b-w4a16/
```

---

## Palanca 2: continuous batching

### Mecánica

El batching estático mantiene el batch fijo: si una petición termina antes, el slot queda
vacío hasta el final del batch. El **continuous batching** inserta nuevas peticiones en
cuanto un slot libera, manteniendo la GPU siempre al máximo de utilización posible.

El efecto energético: la potencia GPU es casi constante (la GPU está siempre activa); el
throughput crece. El resultado es un denominador mayor a potencia similar:

$$\text{J/token}_{\text{batch continuo}} = \frac{\overline{P}}{\text{throughput}_{\uparrow}}$$

Datos medidos ([arXiv 2504.17674](https://arxiv.org/pdf/2504.17674),
[TokenPowerBench arXiv 2512.03024](https://arxiv.org/pdf/2512.03024)):

- vLLM con PagedAttention vs Transformers sin optimizar: −25–40% J/token en cargas
  batch altas.
- Continuous batching online vs static offline: −5% adicional de J/token (pequeño pero
  consistente).
- Batch 32→256 tokens: −25% J/token en Llama-3 70B (economías de escala de kernel).
- Throughput: ×5 respecto a stacks de batching estático a carga equivalente.

El knee de eficiencia en H100 se sitúa en torno a 256–512 tokens de batch; más allá,
el J/token se estabiliza o sube ligeramente.

### Herramientas OSS

vLLM, TGI (Text Generation Inference de HuggingFace), TRT-LLM. El flag relevante en vLLM:
`--max-num-seqs` (máximo de secuencias concurrentes); ajustarlo al tamaño de VRAM disponible
maximiza el batch efectivo.

---

## Palanca 3: power capping

### Mecánica

El power cap fija un techo de potencia instantánea (W). La GPU lo respeta recortando el
clock (DVFS interno). El truco de eficiencia: LLM decode es **memory-bandwidth-bound**; la
GPU ya no está a full clock útil, y bajar el TDP reduce la potencia sin degradar el
throughput de forma proporcional.

### La curva power cap vs throughput (H100 SXM)

Datos de ([arXiv 2604.11391](https://arxiv.org/html/2604.11391v1)) y NERSC
([docs.nersc.gov/jobs/power-capping](https://docs.nersc.gov/jobs/power-capping/)):

| Power cap (W) | % del TDP (700 W) | Throughput relativo (memory-bound) | Eficiencia (tok/W) |
|---|---|---|---|
| 700 W | 100% | 100% | 1,00× |
| 560 W | 80% | ~95% | ~1,19× |
| **490 W** | **70%** | **~90–95%** | **~1,27×** (sweet spot) |
| 420 W | 60% | ~80–85% | ~1,33× (latencia sube) |
| 350 W | 50% | ~75% (H100 alcanza BW máximo a 350 W memory-bound) | ~1,50× |
| 200 W | 29% | ~50% | saturación de frecuencia |

Hallazgo clave de [arXiv 2604.11391](https://arxiv.org/html/2604.11391v1): **el H100 alcanza
su máximo ancho de banda de memoria efectivo con solo ~350 W** en cargas memory-bound
(STriad benchmark), frente a 700 W de TDP. Bajar de 700 W a 490 W (−30% potencia) produce
menos de un 10% de caída de throughput en decode: el J/token mejora un ~20–27%.

Para cargas compute-bound (prefill pesado), el sweet spot se desplaza a 400–500 W, donde el
rendimiento escala de forma casi lineal con el cap; de 500 W a 700 W, la ganancia es solo
~10% de throughput adicional por cada 100 W más.

### Fórmula de J/token con power cap

$$\text{J/token}(P_{\text{cap}}) = \frac{P_{\text{cap}} \times \eta(P_{\text{cap}})}{\text{throughput}_{\text{base}} \times f(P_{\text{cap}})}$$

donde \(\eta(P_{\text{cap}})\) es la fracción de potencia efectivamente consumida bajo el
cap (en cargas memory-bound, la GPU ya no consume todo el cap), y \(f(P_{\text{cap}})\) es
la fracción de throughput resultante. En la zona 490–560 W del H100,
\(\eta \approx 0{,}9\) y \(f \approx 0{,}92\text{–}0{,}95\): el numerador baja más que el
denominador, por lo que el J/token mejora.

### Comandos

```bash
# Fijar el power cap a 490 W en la GPU 0 (H100 SXM, TDP 700 W)
sudo nvidia-smi -i 0 -pl 490

# Verificar el límite aplicado y la potencia en tiempo real
nvidia-smi --query-gpu=power.limit,power.draw --format=csv -l 1

# Con DCGM: leer DCGM_FI_DEV_POWER_USAGE en Prometheus
# y DCGM_FI_DEV_POWER_LIMIT para confirmar que el cap está activo
```

```bash
# Aplicar el cap a todas las GPUs del nodo (script de systemd/cron)
for i in $(seq 0 3); do
  sudo nvidia-smi -i $i -pl 490
done
```

Con DCGM en producción, el cap se puede establecer vía
`dcgmi policy --set powercap:490` o mediante el GPU Operator de NVIDIA (campo
`powerLimit` en el DevicePlugin). Zeus ([ml.energy/zeus](https://ml.energy/zeus/))
permite sweepear caps automáticamente y medir el J/token resultante por configuración.

---

## Palanca 4: DVFS (Dynamic Voltage and Frequency Scaling)

### Mecánica

DVFS es más fino que el power cap: permite ajustar la frecuencia del SM directamente
(`nvidia-smi -lgc` para lock GPU clock) o dejar que el driver la ajuste dinámicamente
según la potencia disponible y la carga. En LLM inference, la asimetría entre fases
es el dato clave:

- **Prefill**: compute-bound. Beneficia de clock máximo. Sensible a reducción de frecuencia.
- **Decode**: memory-bandwidth-bound. El clock del SM apenas importa; lo que manda es el
  ancho de banda HBM.

Esta asimetría es la que explotan los sistemas de DVFS específicos para LLM:

| Sistema | Ahorro energético | Penalidad latencia | Hardware | Fuente |
|---|---|---|---|---|
| DVFS-GPT (HAL) | hasta **32%** en iso-latencia | ~1–2% | A100, RTX 4090 | HAL 05190051 |
| EcoInfer | hasta **25,4%** (media 21,5%) | <5% | A100 | arXiv MDPI Electronics |
| DualScale (prefill/decode disaggregado) | **22–45%** con SLO | 1–6% | H100 | arXiv 2602.18755 |
| GreenLLM (SLO-aware DVFS) | **18–30%** | dentro del SLO | — | arXiv 2508.16449 |

El paper [arXiv 2501.08219](https://arxiv.org/abs/2501.08219) mide que reducir la
frecuencia de GPU de 2.842 MHz a 180 MHz logra un ahorro medio del 42% con solo 1–6% de
aumento de latencia en la fase decode — porque el decode es memory-bound y la frecuencia
del SM no es el cuello.

### Comandos (DVFS manual)

```bash
# Bloquear el clock del SM a 1.200 MHz (H100 boost: 1.980 MHz) para decode
sudo nvidia-smi -i 0 -lgc 1200,1200

# Restaurar el clock dinámico
sudo nvidia-smi -i 0 -rgc

# Modo persistente (necesario para que el lock sobreviva entre trabajos)
sudo nvidia-smi -pm 1
```

Para DVFS automático ajustado al SLO (TPOT objetivo), los sistemas como GreenLLM o
DVFS-GPT miden el tiempo de cada iteración y ajustan la frecuencia en tiempo real, sin
sobrespasar el presupuesto de latencia.

---

## Palanca 5: selección de modelo (SLM, MoE vs denso)

### El efecto de la escala

El J/token escala con el tamaño del modelo, pero de forma sublineal. Para Llama-3
([arXiv 2504.17674](https://arxiv.org/pdf/2504.17674)):

| Modelo | Parámetros | J/token relativo | Factor vs 1B |
|---|---|---|---|
| Llama-3 1B | 1B | 1,0× | referencia |
| Llama-3 8B | 8B | ~2,3× | ×2,3 (no ×8) |
| Llama-3 70B | 70B | ~7,3× | ×7,3 (no ×70) |
| Llama-3 405B | 405B | ~40× | ×40 (no ×405) |

El J/token crece ~7,3× de 1B a 70B, mientras que los parámetros crecen ×70: la
eficiencia de hardware (caches, tensor parallelism, kernels) amortigua la escala.
Aun así, pasar de 70B a 8B recorta el J/token un ~68% si la calidad es suficiente para
la tarea.

### MoE vs denso

Los MoE activan solo un subconjunto de expertos por token (típicamente 2 de 8–64), lo que
reduce el cómputo activo. Pero hay una trampa de implementación:

- OLMoE-1B-7B (MoE, 1B activos) vs OLMo-1B (denso): el MoE consume un **54,24% más**
  de energía por token que el modelo denso de igual tamaño activo
  ([arXiv 2504.17674](https://arxiv.org/pdf/2504.17674)), porque los kernels fusionados
  de los expertos son ~19–63% más lentos que una GEMM densa equivalente.
- OLMoE-1B-7B vs OLMo-7B (denso): el MoE sí es más eficiente (7B activos → solo 1B
  activos, ~7× reducción de FLOPs activos por token).

La regla: MoE es eficiente cuando la comparación es **parámetros totales iguales, activos
menores** (p.ej. Mixtral 8×7B vs Llama-3 70B denso). No es eficiente cuando la comparación
es **parámetros activos iguales** por token.

### Tabla de selección de modelo por caso de uso

| Caso de uso | Modelo recomendado | Razón de eficiencia |
|---|---|---|
| Chat simple, extracción de entidades | SLM 7–8B FP8 | −68% J/token vs 70B |
| RAG con contextos largos | 70B FP8 o MoE 8×7B | calidad/J óptimo en K>2K tokens |
| Código complejo, razonamiento | 70B FP8 o 405B INT4 | calidad no negociable |
| Clasificación, embeddings | modelo dedicado (ej. E5, BGE) | órdenes de magnitud menos J |
| Batch diferible offline | MoE grande (DeepSeek, Mixtral) | alta calidad, throughput batch |

---

## Palanca 6: speculative decoding

### Mecánica

El speculative decoding usa un modelo borrador pequeño (*draft model*) para proponer varios
tokens, que el modelo objetivo verifica en paralelo en un solo forward pass. Si los tokens
son aceptados, se generan K tokens por paso en lugar de 1: throughput potencialmente K×.

### Condición de eficiencia energética

El beneficio en J/token **depende del batch size** ([arXiv 2602.09113](https://arxiv.org/pdf/2602.09113)):

| Batch size | Efecto en J/token | Razón |
|---|---|---|
| 1–16 (batch bajo) | **−hasta 29%** | el draft model llena el tiempo de espera; verificación es barata |
| 32–64 (batch medio) | ~0% (neutro) | el overhead de verificación compensa el ganado |
| 128+ (batch alto) | **+25%** (peor) | GPU saturada; el draft model añade overhead sin ahorrar |

Conclusión: speculative decoding es una palanca de J/token solo en **régimen de baja latencia
(batch≤16)**; en high-throughput serving, es contraproducente en términos de J/token
(aunque reduce latencia TPOT).

### Herramientas OSS

vLLM soporta speculative decoding con `--speculative-model` y `--num-speculative-tokens`.
TRT-LLM también. El draft model debe ser de la misma familia (p.ej. Llama-3 8B para
draft de Llama-3 70B).

---

## Palanca 7: prefix caching y chunked prefill

### Prefix caching

El KV-cache del prefill de un prompt compartido (system prompt, few-shot examples, contexto
de documento) es idéntico entre peticiones. Almacenarlo y reutilizarlo elimina el recompute
del prefill para esa fracción del prompt.

Impacto en energía: el prefill es compute-bound y tira picos de potencia. Eliminar el
prefill repetido elimina esos picos. En escenarios con system prompt fijo de 1.000 tokens
y prompts de usuario de 200 tokens, el ahorro es ~1.000/(1.000+200) = **~83% de la energía
de prefill**. En J/token total, el efecto depende de la longitud del prompt compartido vs
la longitud de generación.

Habilitación en vLLM:
```bash
vllm serve meta-llama/Llama-3-70B-Instruct \
  --enable-prefix-caching \
  --max-num-seqs 256
```

### Chunked prefill (SARATHI)

El chunked prefill parte el prefill en chunks de tamaño fijo y procesa cada chunk junto con
tokens de decode de otras peticiones. El beneficio: el prefill de un prompt largo ya no
bloquea el decode de otras peticiones (reducing TPOT spikes), lo que permite mayor
utilización de la GPU en el tiempo.

En términos de J/token total, el chunked prefill reduce la potencia de pico del nodo
(menos spikes de prefill) y mejora la utilización media, lo que se traduce en ~10–15% menos
de J/token en cargas mixtas con prompts largos ([arXiv 2308.16369](https://arxiv.org/pdf/2308.16369)).

```bash
# Activar chunked prefill en vLLM (tamaño de chunk: 512 tokens)
vllm serve meta-llama/Llama-3-70B-Instruct \
  --enable-chunked-prefill \
  --max-num-batched-tokens 512
```

---

## Palanca 8: scheduling a horas limpias

Esta palanca no reduce el J/token físico, pero sí el **gCO₂/token** de la carga diferible.
La mecánica: mover entrenamiento, ingestión de documentos, re-ranking batch y fine-tuning
a las horas de menor intensidad de carbono de la red.

Datos de impacto de temporal shifting ([ACM SLIT, arXiv 2507.09942](https://arxiv.org/pdf/2507.09942)):

- Reducción de CO₂ por temporal shifting: **hasta 34,7%** para cargas flexibles.
- Con carbon-aware reinforcement learning (Eco-Orchestrator): hasta **70% de offset** en
  despliegues integrados.
- En España, la variación horaria de intensidad es ~80–250 gCO₂/kWh: un factor ~3× en el
  mismo día (ver [del vatio al carbono](https://blog.lo0.es/posts/del-vatio-al-carbono-pue-grid/index.md)).

La implementación práctica usa Kueue o Volcano en Kubernetes, con una métrica de intensidad
de red (ElectricityMaps API o esios) como señal de scheduling. Las cargas se marcan con una
anotación `carbon-deadline` (tiempo máximo de espera tolerable) y el scheduler las coloca
en las horas de mínima intensidad dentro de esa ventana.

```yaml
# Anotación Kueue para scheduling consciente de carbono
metadata:
  annotations:
    kueue.x-k8s.io/carbon-aware: "true"
    kueue.x-k8s.io/carbon-deadline: "8h"
```

---

## La curva power cap vs throughput: el sweet spot

> **Diagrama:** Curva power cap vs throughput en H100 SXM: el sweet spot de eficiencia (J/token mínimo) se sitúa entre 490 y 560 W, donde la reducción de potencia supera la caída de throughput — [verlo en la versión HTML](https://blog.lo0.es/posts/palancas-eficiencia-energetica-inferencia/)

La lectura del gráfico: la curva de potencia (línea continua) cae más rápido que la curva
de throughput (línea discontinua) en la zona 490–560 W. Por encima de 560 W, cada 70 W
adicionales dan solo un ~5% de throughput extra; por debajo de 420 W, el throughput empieza
a caer más rápido que la potencia. El **sweet spot de eficiencia** (J/token mínimo) está
en 490–560 W para cargas decode-bound.

Para cargas compute-bound (prefill puro), el sweet spot se desplaza a 500–600 W: el prefill
satura el cómputo de los SM y necesita más potencia para mantener el throughput.

---

## Cómo medir el efecto y validar la calidad

### Stack de medición

El stack completo para medir el efecto de cada palanca:

| Qué medir | Herramienta | Métrica |
|---|---|---|
| Potencia GPU en tiempo real | DCGM (`DCGM_FI_DEV_POWER_USAGE`) | W por GPU, 100ms |
| J/token en producción | Kepler + vLLM tokens | `rate(kepler_joules) / rate(vllm_tokens)` |
| J/token en banco | Zeus (`ZeusMonitor`) | J medidos durante el benchmark |
| Throughput | vLLM metrics (`vllm:generation_tokens_total`) | tok/s |
| Latencia TPOT | vLLM (`vllm:e2e_request_latency`) | ms/tok |
| Calidad de salida | lm-evaluation-harness | MMLU, HumanEval, etc. |

Ver el stack completo en [herramientas de energía](https://blog.lo0.es/posts/herramientas-energia-deploy-precision-overhead/index.md).

### Protocolo de medición por palanca

```promql
# J/token en tiempo real (Kepler + vLLM en Prometheus)
sum(rate(kepler_container_joules_total{container="vllm"}[5m]))
  /
sum(rate(vllm_generation_tokens_total[5m]))

# Potencia media por GPU (DCGM)
avg by (gpu) (DCGM_FI_DEV_POWER_USAGE)

# Verificar power cap activo
avg by (gpu) (DCGM_FI_DEV_POWER_LIMIT)
```

Con Zeus, el sweep de configuraciones es automático:

```python
from zeus.monitor import ZeusMonitor

monitor = ZeusMonitor(gpu_indices=[0, 1, 2, 3])

with monitor.begin_window("fp8_inference"):
    # lanzar benchmark con vLLM FP8
    run_benchmark(model="llama-3-70b-fp8", num_tokens=10_000)

result = monitor.end_window("fp8_inference")
print(f"J/token: {result.total_energy / 10_000:.4f}")
```

### Validación de calidad

La validación de que la palanca no degrada la calidad se hace con lm-evaluation-harness
([github.com/EleutherAI/lm-evaluation-harness](https://github.com/EleutherAI/lm-evaluation-harness)):

```bash
# Comparar MMLU entre FP16 y FP8
lm_eval --model vllm \
  --model_args pretrained=meta-llama/Llama-3-70B-Instruct,dtype=float16 \
  --tasks mmlu --num_fewshot 5 --output_path ./results/fp16/

lm_eval --model vllm \
  --model_args pretrained=meta-llama/Llama-3-70B-Instruct,quantization=fp8 \
  --tasks mmlu --num_fewshot 5 --output_path ./results/fp8/
```

La diferencia de puntuación en MMLU entre FP16 y FP8 con calibración es típicamente
<1%. Sin calibración puede ser 2–4%.

---

## Tabla de decisión Pareto (energía / latencia / calidad)

| Palanca | J/token | TPOT (latencia) | Calidad | Coste implementación | Reversibilidad |
|---|---|---|---|---|---|
| Cuantización FP8 | ↓↓↓ | ↓ (mejora) | ~ (−<1%) | Bajo (1 flag) | Alta |
| Cuantización INT4 AWQ | ↓↓↓↓ | ↓ (mejora) | ↓ (−1–3%) | Medio (recalibrar) | Alta |
| Continuous batching | ↓↓↓ | ~ (neutro en TPOT) | ~ | Bajo (motor nuevo) | Alta |
| Power cap 70% TDP | ↓↓ | ↑ <10% | ~ | Muy bajo (1 comando) | Inmediata |
| DVFS decode | ↓↓↓ | ↑ <6% | ~ | Medio (script + tuning) | Alta |
| Speculative decoding | ↓ (batch bajo) | ↓ (mejora TTFT) | ~ | Medio (draft model) | Alta |
| Prefix caching | ↓↓ (prefill) | ↓↓ (TTFT mejora) | ~ | Bajo (1 flag) | Alta |
| Chunked prefill | ↓ | ↑ TPOT estable | ~ | Bajo (1 flag) | Alta |
| SLM (7B vs 70B) | ↓↓↓↓ | ↓↓ (mejora mucho) | ↓↓ (−variable) | Alto (re-eval calidad) | Media |
| MoE (vs denso mismo tamaño activo) | ↑ (+54%) | ↑ | ~ | — | — |
| Scheduling a horas limpias | ~ J/token, ↓↓ CO₂ | ~ (para diferible) | ~ | Medio (scheduler) | Alta |

Leyenda: ↓↓↓↓ mejora fuerte · ↓↓↓ mejora significativa · ↓↓ mejora moderada · ↓ mejora leve ·
~ neutro · ↑ empeora · ↑↑ empeora significativamente.

---

## Apilamiento de palancas: efecto combinado

Las palancas son en su mayoría **ortogonales** y se apilan. El impacto combinado máximo
documentado en ([arXiv 2504.17674](https://arxiv.org/pdf/2504.17674)):

> "La aplicación correcta de las optimizaciones de inferencia relevantes puede reducir el
> consumo de energía total hasta un 73% respecto a baselines sin optimizar."

Secuencia recomendada por coste-beneficio:

1. **Motor optimizado** (vLLM, TRT-LLM) con continuous batching: −25–40% inmediato.
2. **Cuantización FP8** (si el hardware lo soporta: H100, A100 con soporte limitado): −30–50%
   adicional sobre el J/token restante.
3. **Power cap al 70% TDP**: −20–30% de potencia con <10% de throughput. Bajo coste.
4. **Prefix caching**: actívalo si hay system prompts o contextos repetidos. Sin coste.
5. **Chunked prefill**: si la carga tiene prompts variables largos.
6. **DVFS en decode**: −22–45% adicional si el SLO lo permite.
7. **Speculative decoding**: solo si el batch es bajo (<16) y la latencia TTFT importa.
8. **Selección de modelo**: pasar a SLM si la calidad es suficiente (evaluar con
   lm-evaluation-harness en tu tarea concreta).

Ejemplo cuantificado en 4×H100 SXM (2.800 W TDP nodo), Llama-3 70B, carga chat:

| Configuración | Potencia (W) | Throughput (tok/s) | J/token |
|---|---|---|---|
| PyTorch FP16, batch estático | ~2.100 | ~400 | **5,25** |
| vLLM FP16, continuous batching | ~2.200 | ~1.800 | **1,22** |
| vLLM FP8, continuous batching | ~2.100 | ~2.400 | **0,875** |
| + power cap 490 W/GPU (1.960 W nodo) | ~1.960 | ~2.160 | **0,907** |
| + prefix caching (40% hit rate) | ~1.960 | ~2.600 | **0,754** |
| + DVFS decode 1.200 MHz | ~1.500 | ~2.400 | **0,625** |

> Los valores son estimaciones ilustrativas basadas en los papers citados aplicados a
> un nodo 4×H100. El J/token real depende de la distribución de prompts, el batch efectivo
> y la temperatura de los modelos. Medirlo con Zeus o DCGM+Kepler es obligatorio.

---

## Hardware de referencia: TDP y rangos de power cap

| GPU | TDP (W) | Rango de cap soportado | Sweet spot decode |
|---|---|---|---|
| H100 SXM 80GB | 700 | 200–700 W | ~490–560 W |
| H100 PCIe 80GB | 350 | 100–350 W | ~245–280 W |
| A100 SXM 80GB | 400 | 100–400 W | ~280–320 W |
| A100 PCIe 80GB | 300 | 100–300 W | ~210–240 W |
| L40S 48GB | 350 | 100–350 W | ~245–280 W |
| RTX 5090 (referencia, PCIe) | 575 | ~100–575 W | ~400–460 W |

Para los rangos exactos: `nvidia-smi -q -d POWER | grep -E "Min|Max|Current"`.

---

## Resumen ejecutivo por rol

| Rol | Primera acción | Segunda acción | Herramienta clave |
|---|---|---|---|
| Operador de cluster | `nvidia-smi -pl [70% TDP]` en todos los nodos | Activar persistent mode | nvidia-smi, DCGM |
| Ingeniero de serving | Migrar a vLLM FP8 con continuous batching | Activar prefix caching | vLLM, llm-compressor |
| Arquitecto de plataforma | Seleccionar el modelo mínimo que cumple el SLO de calidad | Diseñar policy de scheduling por carbono | lm-evaluation-harness, Kueue |
| Equipo de MLOps | Montar sweep de power cap con Zeus | Instrumentar J/token en Prometheus | Zeus, DCGM exporter |

Ver el stack de medición completo en [herramientas de energía](https://blog.lo0.es/posts/herramientas-energia-deploy-precision-overhead/index.md)
y la metodología de J/token en [energía por token](https://blog.lo0.es/posts/energia-por-token-metodologia/index.md).
Para el contexto de leaderboards y benchmarks de referencia de energía, ver [leaderboards de energía LLM](https://blog.lo0.es/posts/leaderboards-energia-llm/index.md).
La conexión con el TCO completo está en [utilización GPU como FinOps](https://blog.lo0.es/posts/utilizacion-gpu-como-finops/index.md).

---

## Fuentes

- arXiv 2504.17674 · Energy Considerations of LLM Inference and Efficiency Optimizations (CMU/Hugging Face, 2025) — https://arxiv.org/pdf/2504.17674
- arXiv 2604.11391 · Architectural Trade-offs: power-capping NVIDIA H100 and H200 (FAU Erlangen, 2026) — https://arxiv.org/html/2604.11391v1
- arXiv 2512.03024 · TokenPowerBench: Benchmarking the Power Consumption of LLM Inference — https://arxiv.org/pdf/2512.03024
- arXiv 2602.09113 · Benchmarking the Energy Savings with Speculative Decoding Strategies — https://arxiv.org/pdf/2602.09113
- arXiv 2501.08219 · Characterizing LLM Inference Energy-Performance Tradeoffs across Workloads and GPU Scaling — https://arxiv.org/abs/2501.08219
- arXiv 2602.18755 · DualScale: Energy-Efficient Disaggregated LLM Serving via Phase-Aware Placement and DVFS — https://arxiv.org/pdf/2602.18755
- arXiv 2508.16449 · GreenLLM: SLO-Aware Dynamic Frequency Scaling for Energy-Efficient LLM Serving — https://arxiv.org/pdf/2508.16449
- HAL 05190051 · DVFS-GPT: Dynamic Voltage and Frequency Scaling for Energy-Efficient LLMs — https://hal.science/hal-05190051
- arXiv 2308.16369 · SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills — https://arxiv.org/pdf/2308.16369
- arXiv 2507.09942 · Green-LLM: Optimal Workload Allocation for Environmentally-Aware Distributed Inference — https://arxiv.org/pdf/2507.09942
- arXiv 2505.06371 · The ML.ENERGY Benchmark: Toward Automated Inference Energy Measurement and Optimization — https://arxiv.org/html/2505.06371v1
- Zeus Project (ml.energy) — https://ml.energy/zeus/
- Zeus · PyTorch blog: Deep Learning Energy Measurement and Optimization — https://pytorch.org/blog/zeus/
- Baseten · 33% faster LLM inference with FP8 quantization — https://www.baseten.co/blog/33-faster-llm-inference-with-fp8-quantization/
- NVIDIA · Managing Power Capping (DGX H100/H200 User Guide) — https://docs.nvidia.com/dgx/dgxh100-user-guide/power-capping.html
- NERSC · GPU Power Capping documentation — https://docs.nersc.gov/jobs/power-capping/
- MLCommons · MLPerf Inference v5.1 results — https://mlcommons.org/2025/09/mlperf-inference-v5-1-results/
- vLLM · Disaggregated Prefill documentation — https://docs.vllm.ai/en/latest/features/disagg_prefill/
- Microsoft Research · Characterizing Power Management Opportunities for LLMs in the Cloud (ASPLOS 2024) — https://www.microsoft.com/en-us/research/wp-content/uploads/2024/03/GPU_Power_ASPLOS_24.pdf
- EcoInfer (MDPI Electronics) · Optimizing Energy Efficiency with Latency Guarantees Through Iteration-Level GPU Frequency Control — https://doi.org/10.3390/electronics15102139

