¿Cuánto cuesta realmente ejecutar un LLM local? (Euros por millón de tokens, medidos)

, por lo que es básicamente gratis”. He dicho eso, probablemente lo hayas dicho tú, y es el tipo de afirmación que suena cierta hasta que alguien la mide. Entonces lo medí.

La caja es “ardi”: una máquina openSUSE con un único RTX 3090 (24 GB). En él ejecuté un punto de referencia controlado: tres modelos locales atendidos por ollama, cada uno impulsado bajo una carga de trabajo fija idéntica, mientras que un panel valoraba cada ejecución según la energía real de la GPU que quemaba. No es una estimación de potencia de diseño térmico, no es una suposición al revés: potencia muestreada desde nvidia-smi cada 10 segundos e integrada en la ventana exacta de inicio → fin de cada ejecución, en mi tarifa eléctrica real día/noche: 0,30 BGN día / 0,18 BGN noche (lev búlgaro: mi tarifa de servicios públicos real; convertida a EUR a lo largo de este artículo con la paridad fija del BCE, 1 BGN ≈ 0,5113€).

El resultado es un número por modelo: euros por millón de tokens de salida. Cinco de los ocho modelos que medí resultaron más baratos que una API alojada en la nube. Tres no lo hicieron, y no son los tres que uno adivinaría sólo por el recuento de parámetros.

La afirmación que quería probar

La sabiduría popular es que la inferencia local es la opción barata: compraste la GPU, el token marginal es gratis, la nube es lo que tiene el medidor en funcionamiento. Cada parte de eso merece un número, así que aquí está el que busqué: el costo marginal de energía de generar un token localmente, modelo por modelo, y cómo se compara con lo que cobra una API alojada de clase "Flash" por el mismo token.

Para que esto fuera una medición y no un argumento, necesitaba mantener constantes tres cosas: la misma carga de trabajo para cada modelo, el mismo hardware y un medidor en el que confiara para leer la GPU durante cada ejecución. La tercera es la parte difícil en casa, que es donde entra en juego el instrumento.

Todas las imágenes y figuras de este artículo fueron creadas por el autor.

el metodo

Tres modelos, elegidos para abarcar el rango de tamaños que en realidad mantengo en la caja: gemma3:1b (pequeño), gemma4:26b (los parámetros Gemma 4–25.8B de Google debajo del capó; ollama simplemente lo redondea a “26b” en la etiqueta) y gemma3:27b (el grande más antiguo). Los tres son pesos GGUF cuantificados con Q4_K_M extraídos a través de ollama, por lo que la comparación es igual en cuanto a la cuantificación. Cada uno recibió la misma carga de trabajo fija (un ciclo de 256 generaciones de tokens que se ejecutan a través de cinco indicaciones fijas) mantenida durante aproximadamente 4 minutos (240 s), por lo que la GPU alcanzó un estado estable en lugar de ser juzgada en una primera llamada en frío.

Mientras se ejecutaba cada modelo, lo seguí como un experimento con precio en HomeLab Monitor: mi propio panel, código abierto, MIT, un contenedor. Muestra la potencia de la GPU de nvidia-smi cada 10 s, y para una ejecución rastreada integra la energía sobre la ventana de inicio → fin de la ejecución en kWh, luego la multiplica por la tarifa vigente (día versus noche), en la moneda con la que lo configuré, BGN. Eso convierte "¿cuánto costó este modelo?" de una conjetura a una cifra medida; Luego lo convierto a EUR para facilitar la lectura.

Luego, la aritmética que convierte una carrera de 4 minutos en una velocidad comparable:

€ por 1 millón de tokens de salida = (run_cost_BGN × 0,5113) ÷ (output_tokens / 1.000.000)

El punto de referencia de generación de tres modelos que aparece a continuación es reproducible de principio a fin. A continuación te explicamos cómo colocarlo en tu propia caja.

Paso 1: abra el monitor (un contenedor)

En la máquina con GPU:

COMPOSE_URL=https://raw.githubusercontent.com/SikamikanikoBG/homelab-monitor/main/docker-compose.yml curl -fsSLO "$COMPOSE_URL" ventana acoplable componer -d

Abra http://:9800. El host en el que se ejecuta aparece inmediatamente: CPU, RAM, discos y (si ve uno) la GPU con VRAM por modelo y consumo de energía en vivo. Sin configuración. Este es el medidor. Verifique la configuración de la moneda y la tarifa con la que está configurado antes de confiar en cualquier cifra de € que le muestre.

Paso 2: crea una clave de ingesta

El script de referencia necesita enviar ejecuciones al concentrador, por lo que necesita una clave. Configuración → Integraciones → Crear clave. La clave (una cadena hlm_…) se muestra una vez; cópiala y no la volverás a ver. Guárdelo en una var env; no lo pegues en el script.

exportar HOMELAB_KEY="hlm_xxxxxxxxxxxxxxxxxxxx"

Panel de integraciones de configuración de HomeLab Monitor que muestra la creación de claves de ingesta y la descarga del cliente Python.

El mismo panel tiene un enlace Descargar cliente para el archivo Python que usará en el Paso 3 y un inicio rápido para copiar y pegar, por lo que esta pantalla cubre los dos pasos siguientes.

Paso 3: capta al pequeño cliente

El centro sirve a su propio cliente Python. Es solo stdlib, no hay nada que instalar pip:

CLIENT_URL=http://:9800/static/homelab_run.py curl -O "$CLIENT_URL"

Ese archivo es toda la API de seguimiento. El patrón es deliberadamente pequeño: configúrelo una vez, luego envuelva cualquier bloque de trabajo en un administrador de contexto de ejecución y registre métricas dentro de él.

importe homelab_run como homelab homelab.configure(url="http://:9800", key="hlm_…") con homelab.run("llm-cost-gemma3-1b", params={"model": "gemma3:1b", "engine": "ollama", "gpu": "RTX 3090 24GB", "num_predict": 256}) como r: # … haz el trabajo… r.log_metric("tokens_per_sec", tps, paso=i)

Cuando se abre el bloque with, el centro marca el inicio de la ejecución; cuando se cierra, marca el final y valora la energía de la GPU quemada en el medio. La ventana es la medida.

Paso 4: escribe el punto de referencia

La carga de trabajo es simplemente /api/generate de ollama en un bucle, leyendo los campos que ollama devuelve para obtener tokens reales por segundo en lugar de una aproximación de reloj de pared. Los dos campos que importan son eval_count (tokens generados) y eval_duration (nanosegundos dedicados a generarlos):

importar json, tiempo, urllib.request OLLAMA = "http://localhost:11434" def ollama_generate(modelo, mensaje): body = json.dumps({ "model": modelo, "prompt": mensaje, "stream": False, "options": {"num_predict": 256, "temperature": 0.7}, }).encode() req = urllib.request.Request(OLLAMA + "/api/generate", data=body, headers={"Content-Type": "application/json"}) con urllib.request.urlopen(req, timeout=600) como resp: return json.loads(resp.read())

Luego conduce cada modelo bajo carga durante un tiempo fijo, envuelto en un recorrido con orugas:

def bench(modelo, duración_s=240): ollama_generate(modelo, "Saluda") # calentamiento – excluir el arranque en frío = homelab.run(f"llm-cost-{model.replace(':', '-')}", params={"model": model, "engine": "ollama", "gpu": "RTX 3090 24GB", "num_predict": 256, "workload": "bucle de aviso fijo"}, etiquetas = ["llm-cost", "benchmark"]) tot_out = 0 t0 = time.time(); paso = 0 con ejecución como r: while time.time() – t0 < duración_s: res = ollama_generate(model, PROMPTS[step % len(PROMPTS)]) ec, ed = res.get("eval_count", 0), res.get("eval_duration", 1) # ed in ns tps = ec / (ed / 1e9) if ed else 0.0 tot_out += ec r.log_metric("tokens_per_sec", round(tps, 2), paso=paso) paso += 1 r.log_params({"total_output_tokens": tot_out}) return run.id, tot_out

Una llamada de calentamiento antes de la ventana cronometrada mantiene la latencia de arranque en frío fuera de la medición. El time.sleep(15) que coloco entre los modelos (no se muestra) mantiene cada ventana de precios limpiamente separada para que la cola de un modelo no se filtre en la factura del siguiente.

Paso 5: lea el resumen y el precio

Ejecute el script para los tres modelos y abra la pestaña Experimentos. Cada ejecución es ahora una fila que lleva su energía y costo reales:

Fila de la pestaña Experimentos que muestra una ejecución de referencia con su energía medida y su coste en euros.

Haga clic en una ejecución y obtendrá la curva de potencia de la GPU para esa ventana exacta, con el título del precio debajo: la materia prima a partir de la cual se calcula la cifra en euros:

Curva de potencia de la GPU para una única prueba comparativa con el título de energía con precio debajo.

El centro también expone el costo de cada ejecución mediante programación, por lo que la división final puede ocurrir en el script:

pulled = homelab.pull(run_id) # costo, energía_kwh, avg_w, curva de potencia – el costo está en BGN eur_per_mtok = round((pulled["cost"] * 0.5113) / (tot_out / 1e6), 4)

los numeros

Más tarde volví y agregué cinco modelos más: GLM-4.5-Air (106B), DeepSeek-R1-Distill (32.8B), Seed-OSS (36B), Devstral (24B) y Qwen3-Coder (30.5B), extraídos de un punto de referencia de agente de codificación separado que ya había ejecutado en la misma caja (misma GPU, misma tarifa, mismo método de costo÷tokens, pero tareas reales de agente de varios pasos en lugar de un bucle de generación dedicado de 240 segundos (que se indica donde importa, en las advertencias a continuación). Ocho modelos, una escala:

Gráfico de euros por millón de tokens de salida en ocho modelos locales en un RTX 3090.
Comparación del costo por token entre los modelos locales evaluados.

Y la referencia de la nube con la que estaba midiendo (precios de lista, junio de 2026): un modelo alojado de clase Flash (Gemini 2.5 Flash, GPT-4o-mini) cuesta alrededor de 0,60 dólares por 1 millón de tokens de salida (~0,55 euros); el nivel más barato (Gemini 3.1 Flash-Lite) cuesta alrededor de $0,40.

la sorpresa

Cinco de los ocho son más baratos que la referencia en la nube. Tres no lo son, y los tres que no lo son no son los tres que elegirías según el número de parámetros.

GLM-4.5-Air es el modelo más grande de la lista, 106 mil millones de parámetros y cuesta 1.040 euros/1 millón, realmente más que la API en la nube, solo electricidad, antes de contar un centavo del precio de compra de la GPU. Esa parte coincide con la intuición original: modelo grande, lento, caro.

Pero DeepSeek-R1-Distill tiene apenas un tercio del tamaño del GLM (32,8 mil millones de parámetros) y es el modelo más caro de toda la lista, a 1,526 euros/1 millón. Consume menos energía que gemma3:27b (155 W frente a 283 W) y sigue siendo el modelo más caro por token de todos los modelos probados.

Una nota metodológica que importa aquí, por adelantado y no oculta: los tres modelos Gemma se midieron en un punto de referencia de generación sostenida de 240 segundos dedicado que construí para este artículo. Los otros cinco, incluido DeepSeek-R1-Distill, provienen de un punto de referencia anterior e independiente de tareas reales de agentes de codificación de varios pasos (llamadas a herramientas, razonamiento de múltiples turnos) en la misma GPU y tarifa, utilizando la misma fórmula de costo-tokens de salida. Esa distinción es la única razón por la que DeepSeek tiene el aspecto que tiene: su velocidad bruta de generación cuando produce tokens activamente es de un respetable 6,7 tokens/seg. Pero la velocidad bruta de generación no es lo que cobra el medidor. El medidor se carga según el tiempo del reloj de pared en la tarjeta, y DeepSeek -un modelo de razonamiento destilado- pasa la mayor parte de ese tiempo deliberando entre generaciones, no generando. Su tasa de entrega efectiva (tokens de salida ÷ tiempo total de ejecución, deliberación incluida) es de 3,7 tokens/seg, la más baja de cualquier modelo probado, muy por debajo del 7,1 efectivo de Seed-OSS y el 5,0 de GLM. Eso es lo que realmente rastrea el precio.

El tamaño nunca fue el mecanismo. La velocidad efectiva lo era, y la velocidad efectiva no es el número con el que normalmente se comparan estos modelos.

El mecanismo

Cada token cuesta vatios ÷ rendimiento. Esa es toda la ecuación: el truco consiste en utilizar el número de rendimiento correcto:

El costo por token se compara con el rendimiento efectivo del reloj de pared, lo que muestra que el costo rastrea la velocidad, no el tamaño.

gemma3:1b es rápido (136 tok/s) y ligero (154 W): barato en ambos ejes, más barato en general. Devstral obtiene la mayor potencia de todos los modelos probados (320 W), pero se mantiene en la mitad de la tabla porque sigue siendo razonablemente rápido. Para los tres modelos Gemma especialmente diseñados, la velocidad de generación bruta es el número que fija el precio: vatios ÷ tok/s bruto reconstruye la relación de costes casi exactamente. Para los cinco modelos de referencia agente, el número que fija el precio es el rendimiento efectivo del reloj de pared, no la velocidad de generación bruta a la que normalmente se cotizarían, y según ese número, Seed-OSS (7,1 tok/s efectivo), GLM-4.5-Air (5,0) y DeepSeek-R1-Distill (3,7) son los tres modelos más lentos probados, exactamente en el orden en que los clasifica su costo. Ninguno de ellos tiene consumos de energía inusuales (141-186 W, en realidad más bajos que varios modelos más baratos); simplemente son lentos una vez que se cuentan las llamadas a herramientas y las lagunas de razonamiento, y un modelo lento paga por cada segundo que sostiene la tarjeta, independientemente del recuento de parámetros.

Lo que *no* estoy reclamando

Esta es la parte que lo mantiene honesto, así que seré franco en cuanto a los bordes:

· Esto es solo electricidad de GPU: medida, marginal y pequeña. Una tirada completa se redondea a una fracción de centavo. No estoy midiendo CPU o DRAM (RAPL era ilegible en este host, por lo que resultaron nulos) y explícitamente no cuento el precio de compra de la GPU, el consumo inactivo, el enfriamiento o mi tiempo. Las cifras de €/1 millón son la tarifa marginal de energía, útil para “qué modelo es más barato seguir generando”, no un coste total de propiedad.

· El costo real del local es la GPU que compraste, no los vatios. Un 3090 se amortiza sólo con un uso elevado y constante. Una caja que está ocupada unos minutos al día paga principalmente por silicio inactivo, y ninguna cifra de electricidad refleja eso. La perspectiva de la energía marginal es honesta acerca de su propio alcance: es el piso, no la factura.

· Dos métodos de medición (consulte “la sorpresa” más arriba para saber por qué es importante). Los tres modelos Gemma: un punto de referencia dedicado a la generación sostenida de 240 segundos. Los otros cinco: un punto de referencia separado para el agente de codificación real, la misma fórmula de costos y tokens, pero un rendimiento efectivo de reloj de pared en lugar de una velocidad de generación bruta, lo que podría decirse que es más representativo de cómo se utilizan realmente estos modelos, no menos, ya que las cargas de trabajo de los agentes reales incluyen llamadas a herramientas y deliberaciones que un ciclo de generación puro nunca incluiría.

· Una GPU, un motor, pesos GGUF cuantificados. Su tarifa, modelo, tamaño de lote, cuantificación y tarjeta moverán todos los números aquí. La mesa es mi caja; el método es la parte transferible.

Así que trate los euros absolutos como ilustrativos y la forma como el hallazgo: el costo por token rastrea la velocidad de entrega efectiva, y eso no rastrea el recuento de parámetros de la manera esperada.

la comida para llevar

Elija el modelo más pequeño y rápido que supere su estándar de calidad; ahí es donde lo "local" realmente paga, por un amplio margen, y no tiene nada que ver con elegir un modelo pequeño porque es pequeño. Qwen3-Coder a 30.5B es más barato por token que gemma4:26b, y gemma3:27b a 27B supera a todos los modelos de estilo de razonamiento de la lista a pesar de ser un modelo simple y denso sin trucos especiales de eficiencia. La variable que importa son los tokens entregados por segundo de reloj de pared, punto, no el número bruto de velocidad de generación con el que generalmente se compara un modelo, y la única forma de saberlo para su modelo y su caja es medirlo.

El instrumento que utilicé es HomeLab Monitor (código abierto, MIT, un contenedor) y el precio de ejecución anterior es exactamente lo que hace su pestaña Experimentos desde el primer momento:

Agregue su host de GPU, cree una clave y los precios de su próximo punto de referencia, en cualquier moneda que realmente haya configurado, lo cual vale la pena verificar antes de publicar el número.

Entonces: cuando buscas el modelo local a través de la API, ¿sabes realmente tu número por token, en la moneda correcta, o estás, como yo, simplemente asumiendo que la GPU lo hace gratuito?