ONNX Runtime es el runtime de inferencia multiplataforma impulsado por Microsoft que convierte ONNX (Open Neural Network Exchange) de especificación a herramienta práctica. Tu modelo PyTorch o TensorFlow, exportado a ONNX, se ejecuta casi igual en servidor Linux, móvil Android, iPhone, browser y edge device. Este artículo cubre cómo usarlo bien, cuándo es la elección correcta y dónde queda corto.
Por qué ONNX importa
El problema que resuelve: fragmentación de runtimes. Entrenas en PyTorch, sirves en TensorFlow Serving. Quieres también en móvil: Core ML en iOS, TensorFlow Lite en Android. Browser: TensorFlow.js. Cada paso es una conversión distinta con su set de bugs.
ONNX ofrece un formato intermedio abierto. ONNX Runtime lo ejecuta. Un solo modelo → muchas plataformas.
Export desde PyTorch
import torch
import torch.onnx
model = MyModel()
model.inference_mode()
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
model,
dummy_input,
"model.onnx",
input_names=["input"],
output_names=["output"],
dynamic_axes={
"input": {0: "batch_size"},
"output": {0: "batch_size"}
},
opset_version=17
)
Puntos clave:
opset_version: versión de operators ONNX. Más nuevo = más ops soportados, pero runtime debe coincidir.dynamic_axes: ejes variables (batch size típicamente). Sin esto, el export es static-shape.- Verificar con
onnx.checker.check_model(model).
Inferencia básica
import onnxruntime as ort
import numpy as np
session = ort.InferenceSession("model.onnx")
input_data = np.random.randn(1, 3, 224, 224).astype(np.float32)
outputs = session.run(None, {"input": input_data})
Simple, sin dependencias pesadas. La memoria de ONNX Runtime es ~15MB base + pesos del modelo.
Execution Providers: el secreto del rendimiento
ONNX Runtime soporta Execution Providers (EPs) que aceleran según hardware:
- CPU: por defecto, optimizado.
- CUDA: GPUs NVIDIA.
- TensorRT: mejor aún en NVIDIA, con conversión adicional.
- OpenVINO: Intel CPUs, GPUs integradas, VPUs.
- CoreML: Apple Silicon.
- DirectML: Windows GPUs (incluidas AMD, Intel).
- ROCm: AMD GPUs Linux.
- WebGPU / WebNN: browser.
- NNAPI: Android.
- QNN: Qualcomm (Snapdragon).
- MIGraphX: AMD data center.
Ejemplo eligiendo EP:
session = ort.InferenceSession(
"model.onnx",
providers=[
"CUDAExecutionProvider",
"CPUExecutionProvider"
]
)
El runtime elige el primer disponible. Fallback seguro si el hardware no está.
Casos donde ONNX brilla
- Apps móviles con modelos ML: el mismo export corre en iOS y Android sin trabajo extra.
- Edge devices heterogéneos: Jetson, Raspberry Pi, industrial gateways.
- Browser inference via onnxruntime-web: modelos corren en tab sin servidor.
- Transición de frameworks: exportar desde PyTorch, servir desde cualquier stack.
- Compliance / control: empresas que quieren evitar dependencia de proveedor ML cloud.
Casos donde ONNX queda corto
- Modelos LLM grandes (>7B params): ONNX Runtime soporta, pero vLLM o TensorRT-LLM son más eficientes.
- Custom ops no estándar: si tu modelo usa kernels PyTorch muy custom, pueden no exportar.
- Training: ONNX Runtime Training existe pero es nicho; PyTorch domina.
- Modelos muy nuevos: los operators cutting-edge pueden no estar en ONNX opset.
Optimizaciones
ONNX Runtime incluye optimizaciones automáticas al cargar:
- Graph optimization: fusion de ops, constant folding.
- Kernel fusion específica por EP.
- Quantization opcional — INT8, INT4 — con degradación mínima de calidad.
Quantization en un line:
from onnxruntime.quantization import quantize_dynamic
quantize_dynamic("model.onnx", "model_int8.onnx")
Reducción típica: 4x tamaño, 2-4x más rápido, <1% pérdida de calidad.
ONNX Runtime Web
Una feature infravalorada: onnxruntime-web ejecuta modelos ONNX directamente en navegador con WebGPU o WebAssembly.
import * as ort from 'onnxruntime-web';
const session = await ort.InferenceSession.create(
'./model.onnx',
{ executionProviders: ['webgpu', 'wasm'] }
);
const feeds = { input: new ort.Tensor('float32', data, [1, 3, 224, 224]) };
const results = await session.run(feeds);
Usos: image classification, object detection, whisper para transcripción — todo en cliente sin servidor.
Mobile: ONNX Runtime Mobile
Versión optimizada para móvil con binarios pequeños:
- Android:
.aarintegrable en proyectos Gradle. - iOS: framework Swift/Objective-C.
- React Native: bindings existentes.
- Flutter: plugins comunitarios.
Para modelos de 20-100MB en apps móviles, es la opción más sencilla.
Alternativas a considerar
- PyTorch JIT / LibTorch: para stay-in-PyTorch deployment.
- TensorFlow Lite: para ecosistema TF, bueno en móvil.
- TensorRT (NVIDIA): ceiling de rendimiento en GPUs NVIDIA, pero lock-in.
- CoreML (Apple): óptimo en Apple Silicon exclusivamente.
- OpenVINO (Intel): excelente en hardware Intel.
ONNX Runtime es el “universal” trade-off: menor top-end que especializados, pero portable.
Workflow típico de desarrollo
Patrón que funciona:
- Entrenar en PyTorch/TF con GPU.
- Export a ONNX con
torch.onnx.export. - Validar que la salida coincide con el modelo original.
- Optimizar:
onnxoptimizer+ quantization si aplica. - Benchmark en cada target (server, móvil, browser).
- Desplegar con ONNX Runtime en cada plataforma.
Para cada target, ~1 día de adaptación vs semanas de rework con otros stacks.
Validación post-export
Crítico: verificar que el modelo exportado produce los mismos outputs que el original:
import onnxruntime as ort
import numpy as np
torch_out = model(test_input).detach().numpy()
session = ort.InferenceSession("model.onnx")
onnx_out = session.run(None, {"input": test_input.numpy()})[0]
assert np.allclose(torch_out, onnx_out, rtol=1e-3, atol=1e-5)
Divergencias comunes:
- Ops custom no soportadas completamente.
- Precision differences (float32 vs float16).
- Batch normalization con sutilezas de training vs inference mode.
Modelos preconvertidos: ONNX Zoo
El ONNX Model Zoo tiene docenas de modelos ya convertidos y verificados: YOLOv8, BERT, ResNet, SSD, MobileNet, y más. Si tu caso encaja con uno, te ahorras el export.
Limitaciones de performance
En benchmarks:
- CPU: ONNX Runtime ≥ TensorFlow, < PyTorch JIT en algunos casos.
- GPU NVIDIA: ONNX Runtime CUDA ~95% de TensorRT, sin la complejidad.
- GPU Apple: CoreML > ONNX Runtime para modelos optimizados a Apple.
- Mobile: competitivo con TFLite en la mayoría.
Si necesitas el absoluto top de rendimiento en una plataforma específica, el runtime nativo de esa plataforma gana. ONNX Runtime gana en portabilidad y simplicidad.
Operación en producción
Checklist:
- Model versioning: hash + metadata en tu registro.
- Monitoring: latency, throughput por session.
- Memory management: sessions pueden acumular si no liberan.
- Warmup: primera inferencia más lenta por kernel compilation.
- Fallback EP: siempre
CPUExecutionProvideral final.
Conclusión
ONNX Runtime es una herramienta potente para equipos que sirven ML en múltiples plataformas o que quieren evitar lock-in con un runtime específico. Su portabilidad es su gran ventaja; su límite es que no es el absoluto top en ninguna plataforma individual. Para apps móviles, edge heterogéneo, inferencia en browser, y transición entre frameworks, es casi siempre la elección sensata. Para workloads de solo-servidor-NVIDIA-grande, puede haber alternativas ligeramente más óptimas. Su madurez y el ecosistema Microsoft detrás le dan continuidad asegurada.
Síguenos en jacar.es para más sobre ML en producción, edge computing y arquitecturas de inferencia.