Saltar a contenido

Metodología de benchmark

asiai sigue estándares de benchmarking establecidos (MLPerf, SPEC CPU 2017, NVIDIA GenAI-Perf) para producir resultados fiables, reproducibles y comparables.

Protocolo

  1. Verificación previa: Rechaza iniciar si la presión de memoria es crítica o el sistema está severamente limitado (<80%)
  2. Calentamiento: 1 generación no cronometrada por motor para preparar compiladores JIT y cachés
  3. Ejecuciones medidas: Por defecto 3 ejecuciones por prompt por motor (configurable con --runs)
  4. Muestreo: temperature=0 (greedy) para salida determinista
  5. Descarga de modelo: Después del benchmark de cada motor, el modelo se descarga para liberar memoria unificada antes de iniciar el siguiente motor. Esto previene la acumulación de memoria y el swapping al comparar múltiples motores con modelos grandes
  6. Enfriamiento adaptativo: Tras la descarga, asiai espera a que la presión de memoria de macOS vuelva a "normal" (máx. 30s), luego añade un mínimo de 5s de enfriamiento térmico
  7. Verificaciones de cordura: Los resultados con tok/s ≤ 0 se descartan. TTFT > 60s o tok/s > 500 generan advertencias (probable swapping o errores de medición)
  8. Reporte: Mediana de tok/s como métrica principal (estándar SPEC), media ± desviación estándar como secundaria
  9. Throttling: Advertencia emitida si thermal_speed_limit < 100% durante cualquier ejecución. La degradación térmica (disminución monótona de tok/s entre ejecuciones, caída ≥ 5%) se detecta e informa
  10. Metadatos: Versión del motor, formato del modelo, cuantización, chip de hardware, versión de macOS almacenados por resultado

Métricas

tok/s — Velocidad de generación

Tokens por segundo de tiempo de generación únicamente, excluyendo el procesamiento del prompt (TTFT).

Ollama (API nativa, /api/generate):

tok_per_sec = eval_count / (eval_duration_ns / 1e9)
Fuente: timing GPU interno reportado por Ollama. Sin sobrecarga de red. Es la medición más precisa.

Motores compatibles con OpenAI (LM Studio, llama.cpp, mlx-lm, vllm-mlx):

generation_s = wall_clock_s - ttft_s
tok_per_sec  = completion_tokens / generation_s
Fuente: reloj de pared del lado del cliente vía streaming SSE. Incluye sobrecarga HTTP por fragmento (~1% más lento que el timing del servidor, validado por validación cruzada).

Conteo de tokens: desde usage.completion_tokens en la respuesta del servidor. Si el servidor no reporta este campo, asiai recurre a len(text) // 4 y registra una advertencia. Este respaldo puede desviarse ~25%.

Validación cruzada (abril 2026, Qwen3.5-35B NVFP4, M4 Pro 64GB):

Método tok/s Delta vs referencia
Ollama nativo (GPU interno) 66.6 referencia
OpenAI streaming (cliente) 66.1 -0.8%

Con tamaños de contexto grandes (ej. 64k tokens), el TTFT puede dominar la duración total. Excluirlo de tok/s evita que generadores rápidos parezcan lentos.

TTFT — Tiempo al primer token

Tiempo entre el envío de la solicitud y la recepción del primer token de salida, en milisegundos.

Desde v1.6.0, asiai mide dos valores de TTFT para Ollama, y uno para todos los demás motores:

Ollama (medición dual):

  • TTFT del lado del servidor (ttft_ms): extraído de prompt_eval_duration en la respuesta de Ollama. Es el tiempo puro de procesamiento del prompt en GPU sin sobrecarga de red — la medición más precisa posible. Reportado como ttft_source: server.
  • TTFT del lado del cliente (ttft_client_ms): medido a la llegada del primer fragmento SSE con contenido. Incluye configuración HTTP, transmisión de solicitud y procesamiento del servidor. Es el mismo método utilizado para todos los demás motores.

Motores compatibles con OpenAI (LM Studio, llama.cpp, mlx-lm, vllm-mlx):

  • TTFT del lado del cliente (ttft_client_ms): medido en el primer fragmento SSE con contenido. Es la única medición disponible ya que estos motores no exponen el timing interno de procesamiento del prompt. Tanto ttft_ms como ttft_client_ms contienen el mismo valor.

Métrica comparable: ttft_client_ms es la métrica comparable entre motores — utiliza el mismo método de medición independientemente del motor. Úsela para comparar TTFT entre diferentes motores. El ttft_ms del lado del servidor de Ollama es más preciso para el tiempo absoluto de procesamiento del prompt, pero no es directamente comparable con otros motores.

Validación cruzada (abril 2026, Qwen3.5-35B NVFP4, M4 Pro 64GB):

Método TTFT Delta
Ollama del lado del servidor (ttft_ms) 27 ms referencia
Ollama del lado del cliente (ttft_client_ms) 51 ms +24 ms

El delta de 24ms representa la sobrecarga HTTP en localhost. Esta sobrecarga es consistente y predecible, pero lo suficientemente significativa como para importar al comparar motores.

Power — Vatios de GPU

Potencia promedio de GPU durante la ejecución, medida mediante el framework Apple IOReport Energy Model (sin necesidad de sudo). Una medición por motor — sin promedios a nivel de sesión.

tok/s/W — Eficiencia energética

tok_per_sec_per_watt = tok_per_sec / power_watts

Varianza — Desviación estándar combinada

Desviación estándar combinada intra-prompt que captura el ruido entre ejecuciones sin mezclar la varianza entre prompts. Utiliza la corrección de Bessel (denominador N-1) para varianza muestral insesgada.

Clasificación de estabilidad:

  • CV < 5% → stable
  • CV < 10% → variable
  • CV >= 10% → unstable

Donde CV = (std_dev / mean) * 100.

VRAM — Uso de memoria

Primario: API nativa del motor (Ollama /api/ps, LM Studio /v1/models). Respaldo: ri_phys_footprint vía ctypes (igual que el Monitor de Actividad). Marcado como "(est.)" en la interfaz.

Seguridad del entorno

asiai realiza verificaciones previas al benchmark:

  1. Presión de memoria: rechaza iniciar si es crítica
  2. Throttling térmico: advierte si el límite de velocidad < 80%
  3. Procesos duplicados: advierte si hay múltiples instancias del mismo motor ejecutándose (ej. dos procesos ollama serve en el mismo puerto)
  4. Tipo de runner del motor: para Ollama, detecta si el runner --mlx-engine o --ollama-engine está activo

Estas verificaciones previenen errores de medición causados por contención de recursos o enrutamiento incorrecto.

Conformidad

Práctica Estado
Verificación previa (presión de memoria + térmica) Implementado
Detección de procesos duplicados Implementado (v1.5.0)
Detección de tipo de runner Ollama (MLX vs llama.cpp) Implementado (v1.5.0)
TTFT separado de tok/s Implementado
Etiquetado de fuente TTFT (server vs client) Implementado (v1.5.0)
Medición dual de TTFT (server + client) Implementado (v1.6.0)
Muestreo determinista (temperature=0) Implementado
Conteo de tokens desde API del servidor (no fragmentos SSE) Implementado (advertencia en respaldo)
Monitoreo de energía por motor (IOReport, sin sudo) Implementado
1 generación de calentamiento por motor Implementado
3 ejecuciones por defecto (mínimo SPEC) Implementado
Mediana como métrica principal (estándar SPEC) Implementado
Desviación estándar combinada intra-prompt (Bessel N-1) Implementado (corregido v1.5.0)
Descarga de modelo entre motores Implementado
Enfriamiento adaptativo (sensible a presión de memoria) Implementado
Verificaciones de cordura (tok/s, límites TTFT) Implementado
Detección de throttling térmico + advertencia Implementado
Detección de degradación térmica (disminución monótona) Implementado
Versión del motor + tipo de runner almacenados por resultado Implementado (v1.5.0)
VRAM universal vía ri_phys_footprint Implementado
Detección de regresión histórica Implementado
Script de validación cruzada (3 métodos comparados) Disponible (scripts/cross-validate-bench.py)

Consideraciones sobre Apple Silicon

Memoria unificada

Apple Silicon comparte memoria entre CPU y GPU. asiai ejecuta los motores secuencialmente y descarga los modelos entre motores para evitar contención de memoria y swapping. La VRAM es reportada nativamente por Ollama y LM Studio; para otros motores, asiai estima el uso de memoria mediante ri_phys_footprint (la métrica de huella física de macOS, igual que el Monitor de Actividad). Los valores estimados se etiquetan como "(est.)" en la interfaz.

Throttling térmico

  • MacBook Air (sin ventilador): throttling severo bajo carga sostenida
  • MacBook Pro (con ventilador): throttling leve
  • Mac Mini/Studio/Pro: refrigeración activa, throttling mínimo

asiai registra thermal_speed_limit por resultado y advierte si se detecta throttling.

Caché KV

Tamaños de contexto grandes (32k+) pueden causar inestabilidad en motores que pre-asignan la caché KV. Configura la longitud de contexto del motor para que coincida con el tamaño real de la prueba para obtener resultados justos.

Medición de energía

asiai mide el consumo de energía de GPU, CPU, ANE y DRAM mediante el framework Apple IOReport Energy Model — sin necesidad de sudo. La energía se mide automáticamente en cada benchmark y cada snapshot de monitoreo.

IOReport lee los mismos contadores de energía del hardware que sudo powermetrics, pero a través de una API de espacio de usuario (libIOReport.dylib vía ctypes). Esto elimina la necesidad de configuración de sudo sin contraseña.

Validación

Validamos cruzadamente IOReport contra sudo powermetrics bajo carga de inferencia LLM en M4 Pro 64GB, usando 10 muestras pareadas por motor a intervalos de 2 segundos:

Motor Promedio IOReport Promedio powermetrics Delta medio Delta máximo
LM Studio (MLX) 12.6 W 12.6 W 0.9% 2.1%
Ollama (llama.cpp) 15.6 W 15.4 W 1.3% 4.1%

Ambos motores confirmaron un delta promedio <1,5% con 10/10 muestras pareadas. La energía de ANE fue 0.000W en las 20 muestras, confirmando que ningún motor LLM utiliza actualmente el Neural Engine.

La opción --power habilita validación cruzada adicional ejecutando simultáneamente IOReport y sudo powermetrics, almacenando ambas lecturas para comparación.

Eficiencia energética

La eficiencia energética (tok/s por vatio) se calcula como tok_per_sec / gpu_watts para cada resultado de benchmark. Esta métrica permite comparar el costo de inferencia entre motores y hardware.

Metadatos

Cada resultado de benchmark almacena: engine, engine_version, model, model_format, model_quantization, hw_chip, os_version, thermal_level, thermal_speed_limit, power_watts, power_source, metrics_version. Esto permite una comparación de regresión justa y benchmarks entre máquinas.