<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Genai-Perf on lo0 — Blog Técnico</title><link>https://blog.lo0.es/tags/genai-perf/</link><description>Recent content in Genai-Perf on lo0 — Blog Técnico</description><generator>Hugo -- gohugo.io</generator><language>es</language><lastBuildDate>Mon, 15 Jun 2026 03:00:00 +0200</lastBuildDate><atom:link href="https://blog.lo0.es/tags/genai-perf/index.xml" rel="self" type="application/rss+xml"/><item><title>GenAI-Perf a fondo: perfilado de inferencia LLM con datos reales</title><link>https://blog.lo0.es/posts/nvidia-genai-perf-a-fondo/</link><pubDate>Mon, 15 Jun 2026 03:00:00 +0200</pubDate><guid>https://blog.lo0.es/posts/nvidia-genai-perf-a-fondo/</guid><description>&lt;blockquote>
&lt;p>Notación: importes en &lt;strong>euros (N EUR)&lt;/strong>, decimales con coma. No se usa el símbolo de dólar
(en este sitio es delimitador de fórmula).&lt;/p>
&lt;/blockquote>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>GenAI-Perf (paquete &lt;code>genai-perf&lt;/code>, parte del ecosistema Triton de NVIDIA) es el profiler de inferencia LLM de referencia para endpoints OpenAI-compatible. Instalable con &lt;code>pip install genai-perf&lt;/code>. Un solo comando de &lt;code>genai-perf profile&lt;/code> produce una tabla de consola con TTFT, ITL, request latency (avg/min/max/P75/P90/P99), output sequence length, output token throughput y request throughput, más artefactos &lt;code>profile_export_genai_perf.json&lt;/code> y &lt;code>.csv&lt;/code>. El subcomando &lt;code>analyze&lt;/code> barre automáticamente concurrencias de 1 a 256 (potencias de 2) y genera un &lt;code>analyze_export_genai_perf.csv&lt;/code> resumen. GenAI-Perf fue declarado &lt;strong>en retirada en abril de 2026&lt;/strong> (sustituido por AIPerf); sigue siendo el benchmark de referencia para corridas históricas y comparaciones documentadas, y la herramienta con más documentación pública de NVIDIA para LLMs pre-2026.&lt;/p>
&lt;hr>
&lt;h2 id="qué-es-genai-perf-y-dónde-encaja">Qué es GenAI-Perf y dónde encaja&lt;/h2>
&lt;p>GenAI-Perf es una herramienta de línea de comandos para medir throughput y latencia de modelos generativos de IA servidos a través de un servidor de inferencia. Forma parte del repositorio &lt;code>triton-inference-server/perf_analyzer&lt;/code> de GitHub y se distribuye como paquete pip (&lt;code>genai-perf&lt;/code>) y dentro del contenedor SDK de Triton (&lt;code>nvcr.io/nvidia/tritonserver:YY.MM-py3-sdk&lt;/code>).&lt;/p>
&lt;p>&lt;strong>Posición en el ecosistema NVIDIA:&lt;/strong>&lt;/p>
&lt;div class="diagram" style="max-width:780px;margin:1rem auto;">
&lt;svg viewBox="0 0 780 200" role="img" aria-label="Ecosistema NVIDIA: Triton Inference Server y TensorRT-LLM como motores, NIM como microservicio, GenAI-Perf como profiler de endpoints, AIPerf como sucesor" xmlns="http://www.w3.org/2000/svg">
&lt;style>.bx{fill:none;stroke:currentColor;stroke-width:1.3}.tl{font:600 12px sans-serif;fill:currentColor}.ts{font:11px sans-serif;fill:currentColor}.ar{fill:none;stroke:currentColor;stroke-width:1.3;marker-end:url(#am)}&lt;/style>
&lt;defs>&lt;marker id="am" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">&lt;path d="M0,0 L10,5 L0,10 z" fill="currentColor"/>&lt;/marker>&lt;/defs>
&lt;rect class="bx" x="20" y="60" width="140" height="44" rx="6"/>&lt;text x="90" y="79" text-anchor="middle" class="tl">Motor de inferencia&lt;/text>&lt;text x="90" y="95" text-anchor="middle" class="ts">Triton + TRT-LLM / vLLM&lt;/text>
&lt;path class="ar" d="M160,82 L200,82"/>
&lt;rect class="bx" x="200" y="60" width="120" height="44" rx="6"/>&lt;text x="260" y="79" text-anchor="middle" class="tl">Endpoint&lt;/text>&lt;text x="260" y="95" text-anchor="middle" class="ts">OpenAI-compatible&lt;/text>
&lt;path class="ar" d="M320,82 L360,82"/>
&lt;rect class="bx" x="360" y="60" width="140" height="44" rx="6"/>&lt;text x="430" y="79" text-anchor="middle" class="tl">GenAI-Perf&lt;/text>&lt;text x="430" y="95" text-anchor="middle" class="ts">profiler (hasta abr-2026)&lt;/text>
&lt;path class="ar" d="M500,82 L540,82"/>
&lt;rect class="bx" x="540" y="60" width="140" height="44" rx="6"/>&lt;text x="610" y="79" text-anchor="middle" class="tl">AIPerf&lt;/text>&lt;text x="610" y="95" text-anchor="middle" class="ts">sucesor (abr-2026+)&lt;/text>
&lt;text x="20" y="155" class="ts">GenAI-Perf funciona contra cualquier endpoint compatible con la API OpenAI (vLLM, NIM, Triton, SGLang, TGI…).&lt;/text>
&lt;text x="20" y="172" class="ts">AIPerf es el sucesor oficial desde abril de 2026 (GitHub: ai-dynamo/aiperf).&lt;/text>
&lt;/svg>
&lt;/div>
&lt;p>&lt;strong>Relación con perf_analyzer:&lt;/strong> GenAI-Perf usa internamente el binario &lt;code>perf_analyzer&lt;/code> de Triton para generar carga y medir latencias. perf_analyzer es el generador de carga de bajo nivel; GenAI-Perf es la capa de alto nivel que añade síntesis de prompts, construcción de payloads OpenAI y las métricas específicas de LLM (TTFT, ITL, longitudes de secuencia).&lt;/p>
&lt;p>&lt;strong>Instalación:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Opción 1: pip (requiere CUDA 12, Ubuntu 24.04, Python 3.10+)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip install genai-perf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Opción 2: contenedor SDK de Triton (recomendado para reproducibilidad)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">RELEASE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;25.01&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -it --net&lt;span class="o">=&lt;/span>host --gpus&lt;span class="o">=&lt;/span>all &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> nvcr.io/nvidia/tritonserver:25.01-py3-sdk
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Dentro del contenedor:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">genai-perf --help
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="métricas-que-produce-genai-perf">Métricas que produce GenAI-Perf&lt;/h2>
&lt;p>Las métricas cubren el ciclo completo de una petición de generación en streaming. Todas se reportan con avg, min, max, P75, P90 y P99 salvo las de throughput (solo avg).&lt;/p>
&lt;h3 id="glosario-de-métricas">Glosario de métricas&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Métrica&lt;/th>
&lt;th>Símbolo&lt;/th>
&lt;th>Definición exacta (GenAI-Perf)&lt;/th>
&lt;th>Unidad&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Time to First Token&lt;/strong>&lt;/td>
&lt;td>TTFT&lt;/td>
&lt;td>Tiempo desde que se envía la petición hasta que se recibe el primer token (incluye cola, prefill y red)&lt;/td>
&lt;td>ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Inter-Token Latency&lt;/strong>&lt;/td>
&lt;td>ITL (= TPOT)&lt;/td>
&lt;td>(\frac{e2e_latency - TTFT}{tokens_salida - 1}) — solo fase de decode, excluye el primer token&lt;/td>
&lt;td>ms/token&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Request Latency&lt;/strong>&lt;/td>
&lt;td>e2e_latency&lt;/td>
&lt;td>(e2e = TTFT + Generation_time) — de la primera petición a la última respuesta&lt;/td>
&lt;td>ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Output Token Throughput&lt;/strong>&lt;/td>
&lt;td>OTT&lt;/td>
&lt;td>(\frac{total_output_tokens}{T_y - T_x}) donde (T_x) = primera petición, (T_y) = último token recibido&lt;/td>
&lt;td>tok/s&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Request Throughput&lt;/strong>&lt;/td>
&lt;td>RPS&lt;/td>
&lt;td>(\frac{total_requests_completados}{T_y - T_x})&lt;/td>
&lt;td>req/s&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Input Sequence Length&lt;/strong>&lt;/td>
&lt;td>ISL&lt;/td>
&lt;td>Longitud media en tokens del prompt de entrada&lt;/td>
&lt;td>tokens&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Output Sequence Length&lt;/strong>&lt;/td>
&lt;td>OSL&lt;/td>
&lt;td>Longitud media en tokens de la respuesta generada&lt;/td>
&lt;td>tokens&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Nota metodológica sobre ITL vs LLMPerf:&lt;/strong> GenAI-Perf excluye el TTFT del cálculo de ITL (solo el decode puro). LLMPerf incluye el TTFT en su media de ITL. Los números no son directamente comparables.&lt;/p>
&lt;p>&lt;strong>Nota metodológica sobre TPS vs LLMPerf:&lt;/strong> GenAI-Perf mide el throughput entre la primera petición y el último token recibido ((T_y - T_x)). LLMPerf usa la duración total del benchmark incluyendo generación de prompts y almacenamiento de respuestas; en escenario de concurrencia 1, esa diferencia puede suponer hasta un 33% de diferencia en la cifra de throughput reportada.&lt;/p>
&lt;h3 id="tabla-de-salida-de-consola-ejemplo-real-trt-llm-backend">Tabla de salida de consola (ejemplo real, TRT-LLM backend)&lt;/h3>
&lt;p>La tabla que imprime GenAI-Perf para un perfil con ISL=200, OSL=100, concurrencia=1:&lt;/p>
&lt;pre tabindex="0">&lt;code> NVIDIA GenAI-Perf | LLM Metrics
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━┓
┃ Statistic ┃ avg ┃ min ┃ max ┃ p99 ┃ p90 ┃ p75 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━┩
│ Time to first token (ms) │ 13.68 │ 11.07 │ 21.50 │ 18.81 │ 14.29 │ 13.97 │
│ Inter token latency (ms) │ 1.86 │ 1.28 │ 2.11 │ 2.11 │ 2.01 │ 1.95 │
│ Request latency (ms) │ 203.70 │ 180.33 │ 228.30 │ 225.45 │ 216.48 │ 211.72 │
│ Output sequence length │ 103.46 │ 95.00 │ 134.00 │ 122.96 │ 108.00 │ 104.75 │
│ Input sequence length │ 200.00 │ 200.00 │ 200.00 │ 200.00 │ 200.00 │ 200.00 │
│ Output token throughput (per sec) │ 504.02 │ N/A │ N/A │ N/A │ N/A │ N/A │
│ Request throughput (per sec) │ 4.87 │ N/A │ N/A │ N/A │ N/A │ N/A │
└───────────────────────────────────┴────────┴────────┴────────┴────────┴────────┴────────┘
&lt;/code>&lt;/pre>&lt;p>&lt;em>(Fuente: docs.nvidia.com/deeplearning/triton-inference-server — tutorial LLM)&lt;/em>&lt;/p>
&lt;hr>
&lt;h2 id="invocación-contra-endpoints-openai-compatible">Invocación contra endpoints OpenAI-compatible&lt;/h2>
&lt;h3 id="modo-profile-un-punto-de-carga">Modo &lt;code>profile&lt;/code>: un punto de carga&lt;/h3>
&lt;p>El subcomando &lt;code>profile&lt;/code> mide un punto de operación fijo (concurrencia o request-rate, ISL/OSL sintéticos).&lt;/p>
&lt;p>&lt;strong>Ejemplo 1: endpoint vLLM (chat, streaming)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Levantar el servidor vLLM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -it --net&lt;span class="o">=&lt;/span>host --rm --gpus&lt;span class="o">=&lt;/span>all &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> vllm/vllm-openai:latest &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --model meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --dtype float16
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Perfilar con GenAI-Perf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">genai-perf profile &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --endpoint-type chat &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --streaming &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --concurrency &lt;span class="m">16&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-mean &lt;span class="m">1024&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-stddev &lt;span class="m">128&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">256&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-stddev &lt;span class="m">0&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean-deterministic &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">200&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">20&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --tokenizer meta-llama/Llama-3.1-70B-Instruct
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Ejemplo 2: endpoint completions (sin streaming)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">genai-perf profile &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --endpoint-type completions &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --concurrency &lt;span class="m">32&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-mean &lt;span class="m">512&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-stddev &lt;span class="m">64&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">128&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">200&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">20&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Ejemplo 3: NVIDIA NIM (endpoint TRT-LLM backend, via Triton)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">genai-perf profile &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta/llama-3.1-70b-instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --backend tensorrtllm &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --streaming &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --concurrency &lt;span class="m">8&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-mean &lt;span class="m">2048&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-stddev &lt;span class="m">0&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">512&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean-deterministic &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">100&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">10&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --generate-plots
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Ejemplo 4: request-rate en lugar de concurrencia (Poisson)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">genai-perf profile &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --endpoint-type chat &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --streaming &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-rate 5.0 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-mean &lt;span class="m">1024&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">256&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">300&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">30&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="flags-principales-y-su-función">Flags principales y su función&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Flag&lt;/th>
&lt;th>Valores típicos&lt;/th>
&lt;th>Función&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>--endpoint-type&lt;/code>&lt;/td>
&lt;td>&lt;code>chat&lt;/code>, &lt;code>completions&lt;/code>, &lt;code>embeddings&lt;/code>&lt;/td>
&lt;td>Tipo de endpoint OpenAI-compatible&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--streaming&lt;/code>&lt;/td>
&lt;td>(booleano)&lt;/td>
&lt;td>Activa streaming SSE; necesario para medir TTFT e ITL reales&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--concurrency&lt;/code>&lt;/td>
&lt;td>1, 8, 16, 32, 64&lt;/td>
&lt;td>Número de peticiones concurrentes mantenidas; GenAI-Perf garantiza N activas en todo momento&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--request-rate&lt;/code>&lt;/td>
&lt;td>1.0, 5.0, 10.0&lt;/td>
&lt;td>Tasa de llegada constante (req/s); no garantiza N activas&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--synthetic-input-tokens-mean&lt;/code>&lt;/td>
&lt;td>128–8192&lt;/td>
&lt;td>Media de tokens ISL sintéticos&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--synthetic-input-tokens-stddev&lt;/code>&lt;/td>
&lt;td>0–512&lt;/td>
&lt;td>Desviación estándar del ISL (0 = fija)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--output-tokens-mean&lt;/code>&lt;/td>
&lt;td>64–2048&lt;/td>
&lt;td>Media de tokens OSL objetivo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--output-tokens-mean-deterministic&lt;/code>&lt;/td>
&lt;td>(booleano)&lt;/td>
&lt;td>Fija el mínimo de output tokens = media objetivo (más preciso con TRT-LLM)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--request-count&lt;/code>&lt;/td>
&lt;td>100–2000&lt;/td>
&lt;td>Número de peticiones a benchmarkear&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--warmup-request-count&lt;/code>&lt;/td>
&lt;td>10–50&lt;/td>
&lt;td>Peticiones de calentamiento descartadas de las métricas&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--generate-plots&lt;/code>&lt;/td>
&lt;td>(booleano)&lt;/td>
&lt;td>Genera gráficas PNG de TTFT vs ISL, ITL vs posición de token, etc.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--tokenizer&lt;/code>&lt;/td>
&lt;td>HF model id&lt;/td>
&lt;td>Tokenizador para contar tokens; obligatorio cuando ISL/OSL importan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--backend&lt;/code>&lt;/td>
&lt;td>&lt;code>tensorrtllm&lt;/code>, &lt;code>vllm&lt;/code>&lt;/td>
&lt;td>Backend de Triton (para servicio directo vía Triton sin endpoint OpenAI)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--extra-inputs&lt;/code>&lt;/td>
&lt;td>&lt;code>ignore_eos:true&lt;/code>&lt;/td>
&lt;td>Parámetros extra de la petición; &lt;code>ignore_eos:true&lt;/code> garantiza OSL consistente&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Nota sobre &lt;code>--concurrency&lt;/code> vs &lt;code>--request-rate&lt;/code>:&lt;/strong> NVIDIA recomienda usar &lt;code>--concurrency&lt;/code>. Con &lt;code>--request-rate&lt;/code>, si la tasa supera el throughput del motor, la cola crece sin límite y las métricas dejan de ser estables. Con &lt;code>--concurrency&lt;/code>, siempre hay exactamente N peticiones activas, lo que da una curva latencia-throughput limpia.&lt;/p>
&lt;h3 id="artefactos-de-salida">Artefactos de salida&lt;/h3>
&lt;p>GenAI-Perf vuelca todos los resultados en un directorio &lt;code>artifacts/&lt;/code>:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Artefacto&lt;/th>
&lt;th>Formato&lt;/th>
&lt;th>Contenido&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>profile_export_genai_perf.json&lt;/code>&lt;/td>
&lt;td>JSON&lt;/td>
&lt;td>Métricas completas (avg, min, max, P75, P90, P99) + argumentos CLI usados&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>profile_export_genai_perf.csv&lt;/code>&lt;/td>
&lt;td>CSV&lt;/td>
&lt;td>Tablas de consola exportadas, listas para import a Excel/pandas&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>profile_export.json&lt;/code>&lt;/td>
&lt;td>JSON&lt;/td>
&lt;td>Datos crudos de perf_analyzer (trazas por petición)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>inputs.json&lt;/code>&lt;/td>
&lt;td>JSON&lt;/td>
&lt;td>Payloads sintéticos enviados (para reproducibilidad)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Gráficas PNG&lt;/td>
&lt;td>PNG&lt;/td>
&lt;td>TTFT analysis, Request latency, TTFT vs ISL, ITL vs posición, ISL vs OSL (con &lt;code>--generate-plots&lt;/code>)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="subcomando-analyze-sweep-automático-de-concurrencia">Subcomando &lt;code>analyze&lt;/code>: sweep automático de concurrencia&lt;/h2>
&lt;p>El subcomando &lt;code>analyze&lt;/code> barre múltiples valores de un parámetro en un solo comando y genera un CSV resumen.&lt;/p>
&lt;h3 id="sweep-de-concurrencia-el-más-usado">Sweep de concurrencia (el más usado)&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Barre concurrencias 1, 2, 4, 8, 16, 32, 64, 128, 256&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">genai-perf analyze &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --endpoint-type chat &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --streaming &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sweep-type concurrency &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sweep-range 1:256 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-mean &lt;span class="m">1024&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">256&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">200&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">20&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="sweep-de-request-rate">Sweep de request-rate&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Barre 2, 4, 6, 8, 10, 12 req/s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">genai-perf analyze &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --endpoint-type chat &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --streaming &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sweep-type request_rate &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sweep-list 2,4,6,8,10,12 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --synthetic-input-tokens-mean &lt;span class="m">1024&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">256&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">200&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">20&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="sweep-de-isl-para-estudiar-el-efecto-del-prefill">Sweep de ISL (para estudiar el efecto del prefill)&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">genai-perf analyze &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -m meta-llama/Llama-3.1-70B-Instruct &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --endpoint-type chat &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --streaming &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sweep-type input_sequence_length &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --sweep-list 256,512,1024,2048,4096 &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --concurrency &lt;span class="m">16&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --output-tokens-mean &lt;span class="m">256&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --request-count &lt;span class="m">200&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --warmup-request-count &lt;span class="m">20&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="estructura-de-artefactos-del-analyze">Estructura de artefactos del &lt;code>analyze&lt;/code>&lt;/h3>
&lt;p>Para un sweep &lt;code>--sweep-type concurrency --sweep-range 1:32&lt;/code>:&lt;/p>
&lt;pre tabindex="0">&lt;code>artifacts/
llama70b-openai-chat-concurrency1/
inputs.json
profile_export.json
profile_export_genai_perf.json
profile_export_genai_perf.csv
llama70b-openai-chat-concurrency2/
...
llama70b-openai-chat-concurrency4/
...
[...]
analyze_export_genai_perf.csv ← resumen de todos los escenarios
checkpoint.json ← permite reanudar sweeps interrumpidos
&lt;/code>&lt;/pre>&lt;h3 id="formato-del-csv-resumen">Formato del CSV resumen&lt;/h3>
&lt;pre tabindex="0">&lt;code class="language-csv" data-lang="csv">Config Name,Concurrency,ISL,p99 TTFT (ms),p99 ITL (ms),p99 Request Latency (ms),Avg. OTT (tok/s),RPS
llama70b_run_0,1,1024,45.2,6.8,1823.4,128.3,0.55
llama70b_run_1,4,1024,48.1,7.1,1901.2,510.7,2.18
llama70b_run_2,8,1024,61.3,7.9,2142.5,989.2,4.12
llama70b_run_3,16,1024,98.7,9.4,2891.3,1741.6,6.88
llama70b_run_4,32,1024,284.1,14.2,4320.8,2134.2,7.14
llama70b_run_5,64,1024,892.4,28.7,8741.2,2251.8,7.23
&lt;/code>&lt;/pre>&lt;p>El CSV resumen incluye también una segunda tabla con métricas de GPU (potencia P99, energía, utilización, memoria) cuando se capturan vía las URLs de telemetría de Triton (&lt;code>--server-metrics-urls http://localhost:8002/metrics&lt;/code>).&lt;/p>
&lt;hr>
&lt;h2 id="tabla-comparativa-genai-perf-vs-guidellm-vs-llmperf-vs-vllm-bench">Tabla comparativa: GenAI-Perf vs GuideLLM vs LLMPerf vs vLLM bench&lt;/h2>
&lt;p>La elección de herramienta cambia el número. No son comparables entre sí sin ajuste.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Dimensión&lt;/th>
&lt;th>&lt;strong>GenAI-Perf&lt;/strong>&lt;/th>
&lt;th>&lt;strong>GuideLLM&lt;/strong>&lt;/th>
&lt;th>&lt;strong>LLMPerf&lt;/strong>&lt;/th>
&lt;th>&lt;strong>vLLM bench serve&lt;/strong>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Origen / mantenedor&lt;/strong>&lt;/td>
&lt;td>NVIDIA / Triton team (en retirada abr-2026)&lt;/td>
&lt;td>Red Hat / proyecto vLLM&lt;/td>
&lt;td>Anyscale / Ray&lt;/td>
&lt;td>proyecto vLLM&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Clase&lt;/strong>&lt;/td>
&lt;td>generador de carga multi-proceso&lt;/td>
&lt;td>generador de carga multi-proceso&lt;/td>
&lt;td>generador de carga multi-proceso&lt;/td>
&lt;td>micro-bench mono-proceso&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Endpoints soportados&lt;/strong>&lt;/td>
&lt;td>OpenAI-compatible + KServe + Triton nativo&lt;/td>
&lt;td>OpenAI-compatible&lt;/td>
&lt;td>OpenAI-compatible&lt;/td>
&lt;td>vLLM nativo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Modo de carga principal&lt;/strong>&lt;/td>
&lt;td>concurrencia fija N (recomendado) o request-rate constante&lt;/td>
&lt;td>synchronous, concurrent, poisson, throughput, &lt;strong>sweep automático&lt;/strong>&lt;/td>
&lt;td>batches de N concurrentes (con draining period al final)&lt;/td>
&lt;td>request-rate, concurrencia&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Draining period&lt;/strong>&lt;/td>
&lt;td>NO — garantiza N activas en todo momento&lt;/td>
&lt;td>NO (poisson)&lt;/td>
&lt;td>SÍ — al final de cada batch el sistema se vacía, la concurrencia cae a 0&lt;/td>
&lt;td>N/A&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Sweep automático&lt;/strong>&lt;/td>
&lt;td>&lt;code>analyze&lt;/code> (concurrencia, request-rate, ISL, OSL)&lt;/td>
&lt;td>&lt;code>--rate-type sweep&lt;/code> (idle a saturación, 10 rondas)&lt;/td>
&lt;td>manual (varias corridas)&lt;/td>
&lt;td>&lt;code>vllm bench sweep serve&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Métricas LLM&lt;/strong>&lt;/td>
&lt;td>TTFT, ITL, e2e latency, OTT, RPS, ISL/OSL&lt;/td>
&lt;td>TTFT, ITL/TPOT, throughput, goodput bajo SLO&lt;/td>
&lt;td>TTFT, ITL (incluye TTFT en el promedio), TPS (duración total del benchmark)&lt;/td>
&lt;td>TTFT, TPOT, throughput&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Diferencia ITL&lt;/strong>&lt;/td>
&lt;td>excluye TTFT: ((e2e - TTFT) / (N_{tok}-1))&lt;/td>
&lt;td>excluye TTFT (mismo que GenAI-Perf)&lt;/td>
&lt;td>incluye TTFT en el promedio&lt;/td>
&lt;td>excluye TTFT&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Diferencia TPS&lt;/strong>&lt;/td>
&lt;td>(total_tokens / (T_y - T_x))&lt;/td>
&lt;td>throughput + goodput bajo SLO&lt;/td>
&lt;td>(total_tokens / (T_{end} - T_{start})) — hasta 33% menor&lt;/td>
&lt;td>(total_tokens / (T_y - T_x))&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Goodput / SLO&lt;/strong>&lt;/td>
&lt;td>NO&lt;/td>
&lt;td>SÍ (clave diferencial)&lt;/td>
&lt;td>NO&lt;/td>
&lt;td>NO&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Exportes&lt;/strong>&lt;/td>
&lt;td>JSON + CSV + PNG + checkpoint&lt;/td>
&lt;td>JSON + YAML + CSV + HTML interactivo&lt;/td>
&lt;td>JSON&lt;/td>
&lt;td>consola / JSON&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Warmup integrado&lt;/strong>&lt;/td>
&lt;td>SÍ (&lt;code>--warmup-request-count&lt;/code>)&lt;/td>
&lt;td>SÍ (peticiones de calentamiento)&lt;/td>
&lt;td>NO nativo&lt;/td>
&lt;td>SÍ&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Datasets reales&lt;/strong>&lt;/td>
&lt;td>OpenOrca, CNN DailyMail, fichero JSONL, moon_cake&lt;/td>
&lt;td>fichero con distribución de tráfico&lt;/td>
&lt;td>fichero JSONL&lt;/td>
&lt;td>sharegpt, random&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>GPU telemetría&lt;/strong>&lt;/td>
&lt;td>SÍ (vía server-metrics-urls de Triton → CSV resumen)&lt;/td>
&lt;td>NO nativo (integrar DCGM aparte)&lt;/td>
&lt;td>NO&lt;/td>
&lt;td>NO&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Cuándo elegir&lt;/strong>&lt;/td>
&lt;td>perfilado fino de un punto de operación, comparación de configs con mismo harness, integración con NIM/Triton&lt;/td>
&lt;td>sweep dirigido por SLO, hallar el codo, dimensionar réplicas&lt;/td>
&lt;td>validación rápida de endpoint en ecosistema Ray&lt;/td>
&lt;td>iterar sobre flags de vLLM&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Regla de comparación justa:&lt;/strong> nunca cruzar números de herramientas distintas para la misma conclusión. Si se comparan vLLM vs TRT-LLM, usar GenAI-Perf contra ambos, con la misma ISL/OSL, la misma concurrencia y el mismo &lt;code>--warmup-request-count&lt;/code>. La herramienta es la constante; el motor es la variable.&lt;/p>
&lt;hr>
&lt;h2 id="perfilado-sobre-4h100-sxm-80-gb-ejemplo-de-sweep-completo">Perfilado sobre 4×H100 SXM 80 GB: ejemplo de sweep completo&lt;/h2>
&lt;p>Hardware de referencia genérico: 4×H100 SXM 80 GB NVLink, modelo Llama-3.1-70B-Instruct FP16, ISL=1024 tokens, OSL=256 tokens, endpoint vLLM.&lt;/p>
&lt;h3 id="resultado-ilustrativo-de-un-sweep-de-concurrencia-164">Resultado ilustrativo de un sweep de concurrencia (1→64)&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Concurrencia&lt;/th>
&lt;th>TTFT P50 (ms)&lt;/th>
&lt;th>TTFT P99 (ms)&lt;/th>
&lt;th>ITL P50 (ms)&lt;/th>
&lt;th>ITL P99 (ms)&lt;/th>
&lt;th>OTT (tok/s)&lt;/th>
&lt;th>RPS&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1&lt;/td>
&lt;td>38&lt;/td>
&lt;td>45&lt;/td>
&lt;td>6,4&lt;/td>
&lt;td>7,1&lt;/td>
&lt;td>130&lt;/td>
&lt;td>0,51&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4&lt;/td>
&lt;td>40&lt;/td>
&lt;td>51&lt;/td>
&lt;td>6,8&lt;/td>
&lt;td>8,2&lt;/td>
&lt;td>510&lt;/td>
&lt;td>2,00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>8&lt;/td>
&lt;td>46&lt;/td>
&lt;td>62&lt;/td>
&lt;td>7,3&lt;/td>
&lt;td>9,4&lt;/td>
&lt;td>980&lt;/td>
&lt;td>3,83&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>16&lt;/td>
&lt;td>68&lt;/td>
&lt;td>98&lt;/td>
&lt;td>8,9&lt;/td>
&lt;td>12,1&lt;/td>
&lt;td>1.720&lt;/td>
&lt;td>6,72&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>32&lt;/td>
&lt;td>145&lt;/td>
&lt;td>284&lt;/td>
&lt;td>13,7&lt;/td>
&lt;td>21,4&lt;/td>
&lt;td>2.130&lt;/td>
&lt;td>8,32&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>48&lt;/td>
&lt;td>380&lt;/td>
&lt;td>740&lt;/td>
&lt;td>22,3&lt;/td>
&lt;td>38,6&lt;/td>
&lt;td>2.280&lt;/td>
&lt;td>8,90&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>64&lt;/td>
&lt;td>890&lt;/td>
&lt;td>1.820&lt;/td>
&lt;td>41,2&lt;/td>
&lt;td>78,3&lt;/td>
&lt;td>2.340&lt;/td>
&lt;td>9,14&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Cómo se lee: el throughput satura alrededor de concurrencia 48–64, mientras el TTFT P99 ya supera los 500 ms a partir de concurrencia 32. El &lt;strong>codo&lt;/strong> (último punto con TTFT P99 &amp;lt; 500 ms) está en concurrencia 16 con 1.720 tok/s útiles. Quien reporte &amp;ldquo;2.340 tok/s&amp;rdquo; (concurrencia 64) describe el throughput máximo, donde el sistema no cumple ningún SLO de chat interactivo.&lt;/p>
&lt;h3 id="fórmulas-de-las-métricas-clave">Fórmulas de las métricas clave&lt;/h3>
&lt;p>$$
\text{ITL} = \frac{e2e_latency - TTFT}{N_{tokens_salida} - 1}
$$&lt;/p>
&lt;p>$$
\text{OTT} = \frac{\sum tokens_salida}{T_y - T_x}
$$&lt;/p>
&lt;p>$$
\text{RPS} = \frac{N_{requests}}{T_y - T_x}
$$&lt;/p>
&lt;p>donde (T_x) es el timestamp de la primera petición enviada y (T_y) el timestamp del último token recibido de la última petición.&lt;/p>
&lt;hr>
&lt;h2 id="perfilado-de-islosl-sintéticos-qué-configurar-para-cada-caso-de-uso">Perfilado de ISL/OSL sintéticos: qué configurar para cada caso de uso&lt;/h2>
&lt;p>Los parámetros ISL/OSL determinan qué motor del sistema se estresa: ISL largo estresa el prefill (KV-cache, TTFT); OSL largo estresa el decode (ITL, ancho de banda de memoria).&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Caso de uso&lt;/th>
&lt;th>ISL típico&lt;/th>
&lt;th>OSL típico&lt;/th>
&lt;th>&lt;code>--synthetic-input-tokens-mean&lt;/code>&lt;/th>
&lt;th>&lt;code>--output-tokens-mean&lt;/code>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Chat interactivo corto&lt;/td>
&lt;td>~300 tok&lt;/td>
&lt;td>~100 tok&lt;/td>
&lt;td>300&lt;/td>
&lt;td>100&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Copilot de código&lt;/td>
&lt;td>~800 tok&lt;/td>
&lt;td>~200 tok&lt;/td>
&lt;td>800&lt;/td>
&lt;td>200&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Resumen de documentos&lt;/td>
&lt;td>~2000 tok&lt;/td>
&lt;td>~256 tok&lt;/td>
&lt;td>2000&lt;/td>
&lt;td>256&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>RAG con contexto largo&lt;/td>
&lt;td>~4096 tok&lt;/td>
&lt;td>~512 tok&lt;/td>
&lt;td>4096&lt;/td>
&lt;td>512&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Batch sin latencia&lt;/td>
&lt;td>~512 tok&lt;/td>
&lt;td>~1024 tok&lt;/td>
&lt;td>512&lt;/td>
&lt;td>1024&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Con la opción &lt;code>--extra-inputs ignore_eos:true&lt;/code> se desactiva el token EOS del motor, forzando que se generen exactamente los tokens pedidos. Imprescindible para medir OSL consistente en TRT-LLM; opcional en vLLM.&lt;/p>
&lt;hr>
&lt;h2 id="metodología-honesta-cómo-no-medir-mal">Metodología honesta: cómo no medir mal&lt;/h2>
&lt;h3 id="1-warmup-obligatorio">1. Warmup obligatorio&lt;/h3>
&lt;p>Sin warmup, las primeras peticiones incluyen la latencia de carga del KV-cache, el autotuning del motor y las inicializaciones. GenAI-Perf aplica una ventana deslizante para detectar estabilidad (ratio max/min dentro de un margen en las últimas 3 mediciones), pero el &lt;code>--warmup-request-count&lt;/code> explícito descarta las primeras N peticiones de las métricas. Valor mínimo recomendado: 10 peticiones (o 5% del total si el total es grande).&lt;/p>
&lt;h3 id="2-el-codo-de-concurrencia-extender-el-sweep-hasta-verlo">2. El codo de concurrencia: extender el sweep hasta verlo&lt;/h3>
&lt;p>El throughput satura al llegar a la max batch size efectiva del motor. Si el sweep se detiene antes de alcanzar la saturación, la &amp;ldquo;capacidad máxima&amp;rdquo; reportada es la última concurrencia probada, no el codo real. La regla: el sweep debe llegar a un punto donde el TTFT P99 haya doblado respecto al valor de baja carga (o donde OTT deje de crecer más de un 5% entre pasos). Solo así el codo es visible.&lt;/p>
&lt;p>Para un sweep &lt;code>--sweep-range 1:256&lt;/code>, GenAI-Perf barre 1, 2, 4, 8, 16, 32, 64, 128, 256 (potencias de 2). En la mayoría de modelos 70B sobre 4×H100, la saturación ocurre entre concurrencia 32 y 64; el rango 1:128 cubre el codo con margen.&lt;/p>
&lt;h3 id="3-concurrencia-vs-request-rate-elegir-bien">3. Concurrencia vs request-rate: elegir bien&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Modo&lt;/th>
&lt;th>Comportamiento&lt;/th>
&lt;th>Cuándo usar&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>--concurrency N&lt;/code>&lt;/td>
&lt;td>Siempre N peticiones activas; cuando una termina, se envía la siguiente&lt;/td>
&lt;td>Curva latencia-throughput limpia; comparación entre configs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>--request-rate R&lt;/code>&lt;/td>
&lt;td>Se envía 1 petición cada 1/R segundos; la cola puede crecer sin límite&lt;/td>
&lt;td>Simular tráfico con llegadas a ritmo constante&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>NVIDIA recomienda &lt;code>--concurrency&lt;/code> para benchmarking. Con &lt;code>--request-rate&lt;/code>, si R &amp;gt; throughput máximo del motor, la cola crece indefinidamente y las métricas se vuelven inestables.&lt;/p>
&lt;h3 id="4-sesgo-mono-proceso-vs-multi-proceso">4. Sesgo mono-proceso vs multi-proceso&lt;/h3>
&lt;p>GenAI-Perf es multi-proceso: mantiene N peticiones concurrentes usando el gestor interno de perf_analyzer. No hay riesgo de saturación del cliente. Esto lo diferencia de &lt;code>vllm bench serve&lt;/code> (mono-proceso), que puede saturarse en el cliente a alta concurrencia y dar métricas de throughput infladas.&lt;/p>
&lt;h3 id="5-ignore_eos-y-osl-inconsistente">5. &lt;code>ignore_eos&lt;/code> y OSL inconsistente&lt;/h3>
&lt;p>Sin &lt;code>--extra-inputs ignore_eos:true&lt;/code>, el motor puede generar menos tokens de los pedidos (si el modelo produce un EOS antes). Esto hace que el OSL real varíe entre peticiones y el ITL se vuelva inconsistente entre corridas. Para benchmarks reproducibles con OSL controlado: activar &lt;code>ignore_eos:true&lt;/code> siempre.&lt;/p>
&lt;h3 id="6-tokenizador-correcto">6. Tokenizador correcto&lt;/h3>
&lt;p>El flag &lt;code>--tokenizer&lt;/code> debe apuntar al modelo que se sirve. Si se omite, GenAI-Perf usa un tokenizador por defecto que puede dar ISL/OSL distintos en tokens del modelo real, haciendo que los números de throughput en tok/s no sean comparables entre modelos con vocabularios diferentes.&lt;/p>
&lt;h3 id="7-una-corrida--un-dato-tres-o-más--un-número">7. Una corrida = un dato; tres o más = un número&lt;/h3>
&lt;p>La varianza entre corridas en condiciones idénticas puede ser del 5–10% en métricas de latencia de cola (P99). Un único perfil no es un número defendible; la media de tres corridas con la misma config lo es.&lt;/p>
&lt;div class="diagram" style="max-width:780px;margin:1rem auto;">
&lt;svg viewBox="0 0 780 170" role="img" aria-label="Flujo de un benchmark reproducible con GenAI-Perf: desplegar motor, calentar, sweep de concurrencia mas alla del codo, recoger JSON, comparar" xmlns="http://www.w3.org/2000/svg">
&lt;style>.bx{fill:none;stroke:currentColor;stroke-width:1.3}.tl{font:600 12px sans-serif;fill:currentColor}.ts{font:11px sans-serif;fill:currentColor}.ar{fill:none;stroke:currentColor;stroke-width:1.3;marker-end:url(#bm)}&lt;/style>
&lt;defs>&lt;marker id="bm" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">&lt;path d="M0,0 L10,5 L0,10 z" fill="currentColor"/>&lt;/marker>&lt;/defs>
&lt;rect class="bx" x="20" y="50" width="120" height="44" rx="6"/>&lt;text x="80" y="69" text-anchor="middle" class="tl">1 · Motor&lt;/text>&lt;text x="80" y="85" text-anchor="middle" class="ts">config pineada&lt;/text>
&lt;path class="ar" d="M140,72 L163,72"/>
&lt;rect class="bx" x="163" y="50" width="120" height="44" rx="6"/>&lt;text x="223" y="69" text-anchor="middle" class="tl">2 · Warmup&lt;/text>&lt;text x="223" y="85" text-anchor="middle" class="ts">≥10 peticiones&lt;/text>
&lt;path class="ar" d="M283,72 L306,72"/>
&lt;rect class="bx" x="306" y="50" width="130" height="44" rx="6"/>&lt;text x="371" y="69" text-anchor="middle" class="tl">3 · Sweep&lt;/text>&lt;text x="371" y="85" text-anchor="middle" class="ts">1:256, pasar el codo&lt;/text>
&lt;path class="ar" d="M436,72 L459,72"/>
&lt;rect class="bx" x="459" y="50" width="130" height="44" rx="6"/>&lt;text x="524" y="69" text-anchor="middle" class="tl">4 · Artefactos&lt;/text>&lt;text x="524" y="85" text-anchor="middle" class="ts">JSON + CSV versionados&lt;/text>
&lt;path class="ar" d="M589,72 L612,72"/>
&lt;rect class="bx" x="612" y="50" width="130" height="44" rx="6"/>&lt;text x="677" y="69" text-anchor="middle" class="tl">5 · Comparar&lt;/text>&lt;text x="677" y="85" text-anchor="middle" class="ts">P99 en el codo&lt;/text>
&lt;text x="20" y="128" class="ts">Pinear: versión de genai-perf, versión del motor, modelo, precisión, ISL/OSL, hardware, tokenizador.&lt;/text>
&lt;text x="20" y="145" class="ts">Sin esos metadatos en el JSON, el numero no es reproducible ni comparable.&lt;/text>
&lt;/svg>
&lt;/div>
&lt;hr>
&lt;h2 id="conexión-con-el-track-de-coste-y-energía">Conexión con el track de coste y energía&lt;/h2>
&lt;p>GenAI-Perf puede capturar métricas de GPU en el mismo CSV resumen si se pasa &lt;code>--server-metrics-urls http://localhost:8002/metrics&lt;/code> (endpoint de métricas de Triton, que expone potencia y utilización vía DCGM). El CSV resumen de &lt;code>analyze&lt;/code> incluye entonces una segunda tabla con P99 de potencia (W), energía (MJ), utilización (%) y memoria (GB) por GPU y por escenario.&lt;/p>
&lt;p>Con esos datos, de un único sweep se obtienen los tres ejes del cuadro de mando:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Eje&lt;/th>
&lt;th>Fuente&lt;/th>
&lt;th>Métrica&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Rendimiento&lt;/td>
&lt;td>GenAI-Perf&lt;/td>
&lt;td>OTT (tok/s), TTFT P99, ITL P99&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Energía&lt;/td>
&lt;td>DCGM vía server-metrics-urls&lt;/td>
&lt;td>Potencia (W) → (J/token = W / OTT)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Coste&lt;/td>
&lt;td>precio del nodo&lt;/td>
&lt;td>EUR/hora → (EUR/token = EUR_{hora} / (OTT \times 3600))&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>La fórmula de coste por millón de tokens:&lt;/p>
&lt;p>$$
CPM = \frac{EUR_{hora}}{OTT \times 3{,}6 \times 10^3}
$$&lt;/p>
&lt;p>donde (OTT) es el output token throughput en tok/s y (CPM) es el coste por millón de tokens en EUR.&lt;/p>
&lt;p>Conecta con &lt;a href="https://blog.lo0.es/posts/observabilidad-gpu-dcgm-llm/">observabilidad GPU con DCGM&lt;/a> para la captura de potencia, y con &lt;a href="https://blog.lo0.es/posts/anatomia-request-llm-mayo-2026/">anatomía de una request LLM&lt;/a> para el desglose de fases (prefill vs decode) que el TTFT y el ITL cuantifican.&lt;/p>
&lt;hr>
&lt;h2 id="estado-2026-genai-perf--aiperf">Estado 2026: GenAI-Perf → AIPerf&lt;/h2>
&lt;p>NVIDIA anunció en abril de 2026 que GenAI-Perf pasa a modo de mantenimiento pasivo (sin nuevas funcionalidades) y que el sucesor activo es &lt;strong>AIPerf&lt;/strong> (&lt;code>github.com/ai-dynamo/aiperf&lt;/code>). AIPerf añade detección automática del punto de saturación (&lt;code>estimatedCapacity&lt;/code>) y está integrado en el pipeline de NVIDIA Dynamo.&lt;/p>
&lt;p>Para benchmarks nuevos en producción: migrar a AIPerf. Para reproducir corridas históricas documentadas con GenAI-Perf o para usar los artefactos de NIM benchmarking de NVIDIA (que usan GenAI-Perf): seguir con GenAI-Perf 25.x.&lt;/p>
&lt;p>El artículo &lt;a href="https://blog.lo0.es/posts/herramientas-benchmark-llm-ficha-a-ficha/">herramientas benchmark LLM ficha a ficha&lt;/a> cubre la comparativa completa incluyendo AIPerf. El artículo &lt;a href="https://blog.lo0.es/posts/guidellm-validacion-slo-bajo-carga/">GuideLLM validación SLO bajo carga&lt;/a> detalla el sweep dirigido por SLO que GenAI-Perf no hace nativamente. Para el contexto de metodología general: &lt;a href="https://blog.lo0.es/posts/benchmarking-llm-frameworks-estado-del-arte/">benchmarking LLM frameworks estado del arte&lt;/a>.&lt;/p>
&lt;hr>
&lt;h2 id="ver-también">Ver también&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://blog.lo0.es/posts/sesgo-medicion-reproducibilidad-bench/">Sesgo de medición y reproducibilidad&lt;/a> — las trampas de configuración que invalidan un sweep de GenAI-Perf aunque los comandos sean correctos: warmup insuficiente, dataset sintético vs real, entorno compartido.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/posts/comparativa-motores-serving-pareto/">Comparativa de motores de serving (vLLM/SGLang/TRT-LLM/Dynamo)&lt;/a> — dónde aterrizan los números medidos con GenAI-Perf: la frontera de Pareto goodput-latencia entre los cuatro motores principales.&lt;/li>
&lt;/ul>
&lt;h2 id="fuentes">Fuentes&lt;/h2>
&lt;ul>
&lt;li>NVIDIA · GenAI-Perf — README oficial — &lt;a href="https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/perf_analyzer/genai-perf/README.html">https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/perf_analyzer/genai-perf/README.html&lt;/a>&lt;/li>
&lt;li>NVIDIA · Tutorial LLM con GenAI-Perf (comandos y tablas de salida reales) — &lt;a href="https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/perf_analyzer/genai-perf/docs/tutorial.html">https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/perf_analyzer/genai-perf/docs/tutorial.html&lt;/a>&lt;/li>
&lt;li>NVIDIA · GenAI-Perf Analyze subcommand (sweep, CSV resumen, checkpoint) — &lt;a href="https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/perf_analyzer/genai-perf/docs/analyze.html">https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/perf_analyzer/genai-perf/docs/analyze.html&lt;/a>&lt;/li>
&lt;li>NVIDIA · NIM LLM Benchmarking — Métricas (definiciones TTFT, ITL, TPS, RPS, fórmulas exactas) — &lt;a href="https://docs.nvidia.com/nim/benchmarking/llm/latest/metrics.html">https://docs.nvidia.com/nim/benchmarking/llm/latest/metrics.html&lt;/a>&lt;/li>
&lt;li>NVIDIA · NIM LLM Benchmarking — Parámetros y buenas prácticas (ISL/OSL, concurrencia vs request-rate, ignore_eos) — &lt;a href="https://docs.nvidia.com/nim/benchmarking/llm/latest/parameters.html">https://docs.nvidia.com/nim/benchmarking/llm/latest/parameters.html&lt;/a>&lt;/li>
&lt;li>NVIDIA Technical Blog · Measuring Generative AI Model Performance Using NVIDIA GenAI-Perf and an OpenAI-Compatible API — &lt;a href="https://developer.nvidia.com/blog/measuring-generative-ai-model-performance-using-nvidia-genai-perf-and-an-openai-compatible-api/">https://developer.nvidia.com/blog/measuring-generative-ai-model-performance-using-nvidia-genai-perf-and-an-openai-compatible-api/&lt;/a>&lt;/li>
&lt;li>GitHub · triton-inference-server/perf_analyzer (genai-perf) — &lt;a href="https://github.com/triton-inference-server/perf_analyzer/blob/main/genai-perf/README.md">https://github.com/triton-inference-server/perf_analyzer/blob/main/genai-perf/README.md&lt;/a>&lt;/li>
&lt;li>GitHub · ray-project/llmperf (métricas y diferencias metodológicas) — &lt;a href="https://github.com/ray-project/llmperf">https://github.com/ray-project/llmperf&lt;/a>&lt;/li>
&lt;li>PyPI · nvidia-genai-perf-eval — &lt;a href="https://pypi.org/project/nvidia-genai-perf-eval/">https://pypi.org/project/nvidia-genai-perf-eval/&lt;/a>&lt;/li>
&lt;li>Macnica · Benchmarking LLM Applications Part 1: What is GenAI-Perf? — &lt;a href="https://www.macnica.co.jp/en/business/semiconductor/articles/nvidia/145977/">https://www.macnica.co.jp/en/business/semiconductor/articles/nvidia/145977/&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>