Source document
Metodología de medición
Spanish text, transcribed from the repository. The unformatted
source is
benchmarks/methodology.md.
Este documento existe porque una cifra sin método no es un dato: es una afirmación. Aquí se registra qué se midió, cómo, con qué binario, cuántas veces, y —lo más importante— qué no se midió.
Es el único documento de metodología del repositorio. Al final lleva un anexo histórico con la metodología de la iteración v4, conservada para que una cifra antigua pueda rastrearse hasta el método que la produjo; las dos versiones estuvieron en ficheros separados y se fusionaron para que no hubiera dos lugares donde buscar cómo se mide.
Reglas
- Siempre binario de release. El benchmark de cómputo da 0,49 GFLOPS en debug y 34-37 GFLOPS en release: 70× de diferencia. El binario se niega a medir en debug (
--allow-debuglo fuerza, y entonces la cifra no sirve para decidir nada).verify.shcomprueba que la negativa ocurre de verdad. - Mediciones intercaladas cuando se comparan dos versiones. Un A/B en dos sesiones distintas mide la deriva térmica del equipo, no el cambio. En la fase 6 una comparación secuencial dio «681 → 627 rps» (una regresión del 8 %); al intercalar A/B en el mismo proceso la diferencia real era 613,8 → 614,2 rps, ruido puro. Ver
hot-paths.md. - Nada se declara medido sin un comando reproducible. Cada tabla indica cómo se obtuvo.
- Lo que no se midió se dice. Un hueco honesto es información; un número inventado es un error con fecha.
Qué mide cada herramienta
| Herramienta | Qué mide | Repeticiones | Dónde se guarda |
|---|---|---|---|
hecate-node profile | GFLOPS, ancho de banda, disco, latencia de red del nodo local | 3 (matmul), 21 muestras (red) | docs/benchmarks/hardware-local.json |
hecate-node bench --mock | Latencia y throughput del plano de control con datos simulados | --requests por nivel, 3 niveles | tabla en README.md |
hecate-node bench --compute-latency-ms N | Lo mismo, con cómputo inyectado para que el camino caliente tenga carga realista | 5 repeticiones intercaladas | hot-paths.md |
scripts/measure-host-guarantee.ps1 | CPU y RAM del proceso, y latencia bajo carga externa del host | ventana de 25 s, muestreo 250 ms | docs/benchmarks/host-guarantee.json |
cargo test --workspace | Corrección, no rendimiento | 1 | — |
just fuzz | Robustez ante bytes basura | 60 s por defecto | — |
Por qué bench necesita --compute-latency-ms
Con el plano de datos simulado a 0 ms, una petición atraviesa el camino caliente en microsegundos: el tiempo se va en TCP y en el framing, y cualquier punto de serialización queda invisible. Eso explica que optimizaciones estructurales correctas (quitar un cerrojo exclusivo del camino caliente) no mostraran mejora en la fase 6.
Con --compute-latency-ms 5 el mock tarda 5 ms por fragmento, como un modelo pequeño real. Un pipeline de 3 nodos y 12 capas atraviesa unos diez fragmentos, de ahí p50 ≈ 50 ms. En ese escenario el cerrojo sí se solapa entre peticiones… y aun así la diferencia medida fue inexistente. La conclusión honesta está en hot-paths.md.
Qué NO se ha medido
| Cosa | Por qué |
|---|---|
| Perfil de los tres nodos del plan (Geekom, T14, ThinkPad antiguo) | no hay acceso de red; sus perfiles son declarados, no medidos (ver portability.md) |
| Garantía del 30 % de CPU/RAM en esos tres nodos | misma razón: sólo se ha medido este equipo |
| Rendimiento con un modelo de verdad (PyTorch) | el plano de datos de las mediciones es simulado; con cómputo real las cifras serían otras |
| Ancho de banda de red entre nodos | sólo hay loopback en este equipo (0,036 ms), que no es un enlace |
| Consumo energético | el catálogo lo predice (predict_energy_j), no se mide con vatímetro |
| GPU AMD / Apple Silicon | no hay hardware para probarlo |
Cómo leer las cifras de este repositorio
34-37 GFLOPSes un suelo, no un techo: el benchmark es una multiplicación de matrices sin SIMD explícito ni BLAS. Untorch.matmuldaría mucho más.12-20 GB/svaría entre ejecuciones (copia de 32 MiB); el rango importa más que el punto medio.- Las latencias del pipeline son del plano de control con datos simulados. Incluyen TCP, framing y enrutamiento; no incluyen inferencia real.
- La huella del 8,1 % de CPU es del plano de control. Con el plano de datos cargando un modelo, la CPU será otra cosa: la garantía de convivencia se refiere al enjambre completo y hoy sólo está verificada para el control.
Reproducir desde cero
cargo build --release -p hecate_node
./target/release/hecate-node profile --out docs/benchmarks/hardware-local.json
just bench 400
just guarantee 25
just fuzz 60
Todo sin red salvo just links, que es la única tarea que sale a Internet y por eso no está en just check.
Anexo histórico · metodología de medida v4
Este anexo se conserva por trazabilidad: describe cómo se comparó la iteración v4 de la arquitectura interna contra la v3, con las cifras marcadas [medido] y [pendiente]. No es la metodología vigente —ésa es la de arriba— y sus comparaciones se refieren a versiones internas que ya no existen en el árbol. Se documenta para que una cifra antigua pueda rastrearse hasta el método con el que se obtuvo, no para volver a usarla.
Metodología de medida v4: qué comparar y cómo no engañarse
Esta metodología describe cómo medir la mejora de v4 sobre v3. Las cifras que aparecen como [medido] son reproducibles hoy; las que aparecen como [pendiente] requieren hardware o campañas que no se han ejecutado. La distinción no es retórica: un documento de benchmarks que mezcla ambas es un documento de marketing.
1. Qué se mide
| Magnitud | Unidad | Por qué importa |
|---|---|---|
| Latencia p50 / p95 / p99 por token | ms | p50 engaña: el clúster se juzga por la cola |
| Throughput sostenible | tok/s | lo que aguanta sin divergir |
| Tiempo de failover | ms | cuánto se degrada el servicio cuando cae un nodo |
| Tráfico entre nodos por token | bytes | distingue MoE (0) de pipeline (>0) |
| Utilización por etapa | ρ | si alguna etapa supera 1.0, la latencia diverge |
| Memoria por nodo | bytes | el coste real de replicar el tronco |
La regla que ordena todo: un benchmark que sólo publica p50 no está midiendo un clúster, está midiendo una máquina. La cola es donde aparece el comportamiento distribuido.
2. v3 frente a v4, magnitud a magnitud
2.1 Latencia de red
| v3 | v4 | Cómo se mide | |
|---|---|---|---|
| Transporte | gRPC sobre HTTP/2 | TransportEngine con TCP + sonda RDMA | transport::tests (loopback) |
| Framing | Protobuf por mensaje | u32 BE + payload crudo | round_trip_preserves_bytes |
| Coste por salto en el planificador | no modelado | PlanOptions::hop_ms | network_hops_cost_proportionally |
[medido] el framing: ida y vuelta de 1 KiB en loopback, con contadores de bytes y tramas. [pendiente] el RTT real LAN y la comparación con gRPC: requiere dos máquinas y un arnés de captura.
Lo que no se puede afirmar: que v4 tenga menos latencia de red que v3 en producción. El motor TCP es más ligero que gRPC por mensaje, pero el plano de datos sigue hablando gRPC. La mejora está en el planificador (modela el coste de red) y en la abstracción (cambiar de transporte no toca la lógica), no en un número de milisegundos medido.
2.2 Partición
| v3 | v4 | |
|---|---|---|
| Unidad | capa completa | capa, cabeza de atención o sub-bloque FFN |
| Selección | reparto ponderado fijo | mínimo coste entre 3 granularidades |
| Estabilidad | no comprobada | lyapunov_stability_check con margen 0.95 |
[medido] con la topología de ejemplo (12 capas, 3 nodos de 7.32 / 2.76 / 0.96 capas-equivalentes de capacidad):
| Granularidad | Capas colocadas | Desbordamiento | Latencia estimada |
|---|---|---|---|
layer | 9.0 | 3.0 capas → 120 ms | ~165 ms |
attention | 11.04 | ~1.0 capa → 40 ms | ~44 ms |
La relación 165/44 ≈ 3.7× sale del modelo de coste, no de una medición de reloj. Es una predicción del planificador, y debe contrastarse con cargo run -p hecate_node -- bench antes de publicarla como mejora real.
[pendiente] la comparación de extremo a extremo con un modelo real (LLaMA-7B) en dos nodos físicos. Es el criterio de aceptación de la semana 2 del plan y no está cumplido: falta hardware con capacidad para el modelo.
2.3 MoE
[medido] OLMoE sobre la topología de ejemplo:
covered_experts: 1024/1024 balanced: true (342/341/341)
per_token_cross_node_traffic_bytes: 0
session_histogram: {gpu: 67, laptop: 68, mini: 65} de 200
peak_memory_utilization: 0.17
[medido] Mixtral en dos nodos domésticos: rechazado por capacidad, con el motivo (384 GB de expertos). Un planificador que dice "no cabe" es más útil que uno que genera un plan que revienta.
[pendiente] cargar un MoE real en dos nodos y verificar con captura de red que no hay tráfico de inferencia. Hoy el cero es una invariante del plan, no una observación de red.
2.4 Crecimiento
[medido] grow_depth sobre un sustrato congelado: la pérdida baja, el 90 %+ de los parámetros no se entrena, y el test verifica que sólo la capa nueva conserva requires_grad.
[medido] merge_with_nash con pérdidas 0.05 y 5.0: el resultado queda más cerca del adaptador bueno que del punto medio que daría FedAvg.
[pendiente] la mejora en una tarea de razonamiento real, que es el criterio de la semana
- La tarea sintética demuestra el mecanismo, no la utilidad.
2.5 Decisión (JEV)
[medido] contra un servidor local: elección válida respetada, opción inexistente descartada, timeout < 350 ms con timeout = 50 ms, endpoint inalcanzable degradado.
[pendiente] todo lo que implique el servicio real: precisión de ruta, latencia p50/p95 de decisión, y comparación con el router determinista.
3. Plantilla de publicación
## Entorno
CPU: <modelo> (<n> hilos) GPU: <modelo> (<n> GB) Red: <tipo>
Rust: <versión> Python: <versión> Modelo: <nombre> <cuantización>
## Latencia por token (n = 1000 peticiones)
| Etapas | p50 | p95 | p99 | tok/s |
|---|---|---|---|---|
| 2 | | | | |
| 3 | | | | |
## Failover
| Escenario | Tiempo hasta primera respuesta correcta |
|---|---|
| caída del nodo de cola | |
| caída del nodo de cabeza | |
## Tráfico entre nodos
| Paradigma | bytes/token (captura) |
|---|---|
| pipeline denso | |
| MoE replicado | 0 (esperado) |
4. Cómo no engañarse
- Tres repeticiones como mínimo, y publicar la dispersión. Un número sin varianza no es un resultado, es una anécdota.
- Calentar antes de medir. El primer token paga compilación de kernels, apertura de conexiones y carga de pesos.
- Separar control y datos.
bench --mockmide el plano de control;--data-planeincluye el salto real. Mezclarlos atribuye al diseño lo que es coste de serialización. - No comparar con una configuración por defecto distinta. Si v3 usaba 16 hilos y v4 seis, la mejora es del cambio de hilos.
- Publicar los rechazos. "Mixtral no cabe en dos nodos" es un resultado. Ocultarlo convierte el benchmark en un folleto.
5. Estado real de la campaña
| Semana | Entregable | Estado |
|---|---|---|
| 1 | Transporte con abstracción | ✅ TCP completo + sonda RDMA · ❌ motor RoCEv2 |
| 2 | Partición de grano fino | ✅ planificador · ❌ medida end-to-end con LLaMA-7B |
| 3 | MoE sin tráfico entre nodos | ✅ planificador · ❌ captura de red |
| 4 | JEV como orquestador | ✅ cliente + degradación · ❌ contraste con el servicio real |
| 5 | Crecimiento modular | ✅ mecanismo medido en tarea sintética · ❌ tarea de razonamiento |
| 6 | Benchmarks v3–v4 | ❌ no iniciada (depende de las anteriores) |
Esta tabla es la parte más importante del documento. Un plan de seis semanas con seis semanas verdes sería la señal de que no se está midiendo nada.