Uso de bibliotecas de código abierto para redes neuronales en C++
Introducción
La IA moderna a menudo ingresa a una empresa a través de Python, computadoras portátiles, entornos de demostración y la comprensible emoción de ver un modelo funcionar por primera vez. Esa fase es real, útil e incluso un poco mágica. Es donde la curiosidad es barata y la iteración es rápida. Pero la vida de un producto real no termina con la demostración. Un modelo que debe atender a los clientes, encajar en un backend, ejecutarse en hardware de fábrica, vivir dentro de un producto de escritorio o sobrevivir a malas condiciones de red ya no es sólo un modelo. Se convierte en un componente de un sistema, y es en los sistemas donde la madurez de la ingeniería comienza a importar.
Ese es el momento en que C++ regresa a la sala. No porque los ingenieros sean sentimentales con el pasado, y no porque cada problema de IA deba convertirse en un problema nativo, sino porque la producción plantea preguntas que la experimentación de alto nivel sólo puede posponer durante un tiempo. ¿Cuánta memoria necesita realmente el proceso? ¿Cuál es la latencia de estado estable bajo carga? ¿Puede el tiempo de inicio sobrevivir al ajuste de escala automático? ¿Puede el tiempo de ejecución vivir dentro de una aplicación nativa existente? ¿Podemos enviar la misma ruta de inferencia a un servidor, una caja perimetral y una estación de trabajo del operador sin reconstruir todo el producto en torno a una pila de investigación?
Las bibliotecas de código abierto son las que hacen posible esta transición sin ceder el control a una caja negra del proveedor. Nos brindan tiempos de ejecución estables, abstracciones tensoriales, núcleos optimizados, rutas de ejecución cuantificadas, backends compatibles con el hardware y, en la reciente era LLM, motores de inferencia locales sorprendentemente capaces. Pero la abundancia de bibliotecas también puede hacer que el panorama sea confuso. Los ingenieros a menudo preguntan qué biblioteca es mejor cuando la mejor pregunta es qué biblioteca es honesta sobre el trabajo que tenemos por delante.
Este artículo toma ese camino más fundamentado. Consideraremos las principales bibliotecas relevantes de C++ en IA no como insignias de identidad sino como personalidades de ingeniería con fortalezas, puntos ciegos y suposiciones operativas. Al final, el objetivo no es simplemente conocer los nombres ONNX Runtime, LibTorch, oneDNN, OpenVINO, TensorFlow Lite y llama.cpp. El objetivo es entender cuándo ayuda cada uno, cuándo se vuelve demasiado pesado, cuándo se vuelve demasiado estrecho y cómo elegir sin dejarse llevar por la moda.
Por qué los sistemas de inteligencia artificial siguen regresando a C++
Hay un ritmo en la entrega de IA que vale la pena nombrar claramente, porque una vez que lo ves, muchas opciones de arquitectura se vuelven más fáciles de entender. Primero está la etapa de descubrimiento. Los investigadores e ingenieros de productos todavía están aprendiendo qué puede hacer el modelo, qué datos necesita y dónde puede residir realmente el valor. En esa etapa, la expresividad vence a la disciplina. Experimentación rápida, herramientas Python enriquecidas y marcos de investigación flexibles son exactamente lo que el equipo necesita.
Luego viene la segunda etapa, menos glamorosa, donde un prototipo comienza a acumular obligaciones. Un equipo de soporte debe comprender las fallas. Un equipo de SRE quiere un comportamiento de inicio y memoria predecible. Finanzas quiere saber si la factura de servicio es un aumento temporal o una fuga permanente. Un cliente integrado pregunta si el modelo se puede ejecutar sin conexión. Una revisión de seguridad pregunta qué se incluye exactamente dentro del binario y qué partes se pueden auditar. De repente, el modelo deja de ser un artefacto de investigación y se convierte en ciudadano de un entorno de producción.
C++ sigue regresando en ese punto porque permite que la ingeniería responda preguntas concretas en lugar de agitarlas con la mano. Un servicio nativo puede controlar estrategias de asignación, grupos de subprocesos, límites ABI, empaquetado, optimizaciones específicas de CPU e integración con subsistemas existentes sensibles al rendimiento. Ese control no siempre es necesario. Pero cuando es necesario, es muy difícil fingir con retórica.
Un contraejemplo útil ayuda aquí. Si su equipo está creando un clasificador de documentos interno con poca carga que se ejecuta una vez cada hora, el camino de menor resistencia puede ser un servicio Python con un marco de servicio estable y muy poco código nativo. No hay nada de vergonzoso en eso. Por otro lado, si el mismo equipo está incorporando inferencia dentro de una aplicación de escritorio C++ sensible a la latencia, enviándola a un dispositivo de borde con recursos limitados o insertando la ejecución del modelo directamente en una ruta de backend activa, entonces pretender que el lenguaje de ejecución no importa se vuelve costoso muy rápidamente. En otras palabras, C++ no es la respuesta a todos los problemas de la IA, pero sigue siendo una de las respuestas más serias siempre que el propio sistema se convierte en el problema.
Las bibliotecas como personalidades de la ingeniería
La forma más fácil de perderse en este ecosistema es tratar a cada biblioteca como si estuviera compitiendo por el mismo trabajo. No lo son. Un marco orientado a la capacitación, un tiempo de ejecución de inferencia portátil, una biblioteca de kernel y un motor LLM local resuelven diferentes problemas. Si las agrupamos en una categoría llamada bibliotecas de IA, terminamos tomando decisiones basadas en la familiaridad con la marca en lugar del diseño del sistema.
ONNX Runtime es, en muchos entornos de producción, la opción más disciplinada y menos teatral. Se basa en una promesa clara: exportar el modelo a un formato estable, cargarlo a través de un tiempo de ejecución que se centre en la ejecución y dejar que la aplicación sea dueña del resto del sistema. Eso suena simple, y la simplicidad es exactamente la razón por la que es poderoso. ONNX Runtime suele ser la respuesta correcta cuando la fase de investigación ya se ha realizado en otro lugar y lo que queda es el trabajo sobrio de servir a la inferencia de forma repetida, portátil y con un comportamiento operativo predecible. Un backend de visión por computadora que recibe imágenes, normaliza tensores, ejecuta un gráfico conocido y devuelve resultados a un servicio C++ existente es una historia ideal de ONNX Runtime. Una mala opción sería un producto cuyo valor central dependa del comportamiento dinámico del tiempo de entrenamiento, la cirugía gráfica frecuente dentro de la aplicación o un conjunto de operadores personalizados en constante cambio que hacen que la exportación sea frágil. En tal caso, el límite del tiempo de ejecución que al principio parecía limpio puede convertirse en una fuente de fricción.
LibTorch tiene un carácter diferente. No es principalmente un límite de ejecución ligero. Es la cara C++ de un marco completo de aprendizaje profundo. Eso lo hace más pesado, pero también más expresivo. Cuando una aplicación nativa realmente necesita poseer operaciones tensoriales, construir modelos, realizar manipulaciones similares a las de entrenamiento o permanecer cerca de la semántica de PyTorch durante el desarrollo y la producción, LibTorch se vuelve más atractivo que ONNX Runtime. Hay cierta honestidad al elegirlo cuando el producto realmente necesita un marco y no solo un tiempo de ejecución. El contraejemplo es igualmente importante. A veces, los equipos adoptan LibTorch para realizar inferencias estáticas simples porque se sienten prestigiosos o preparados para el futuro. Luego descubren que importaron una superficie conceptual y operativa mucho mayor que la carga de trabajo requerida. Un pequeño servicio de inferencia que solo necesita cargar un gráfico de modelo estable puede pagar esa decisión en tamaño del paquete, complejidad y esfuerzo de depuración.
oneDNN y OpenVINO viven más cerca del metal y recompensan una mentalidad más consciente del rendimiento. oneDNN no suele ser la biblioteca a la que recurre porque desea una historia completa del producto. Es la biblioteca que usted aprecia cuando los núcleos de CPU, los formatos de memoria y la eficiencia a nivel de operador se vuelven lo suficientemente importantes como para merecer atención directa. Muchos equipos lo utilizan indirectamente a través de tiempos de ejecución de nivel superior, lo que suele ser una buena idea. OpenVINO, mientras tanto, se encuentra en un lugar más estratégico. Ayuda a los equipos que se preocupan por la implementación orientada a Intel, la optimización de gráficos y la ejecución basada en hardware sin querer administrar manualmente cada detalle de bajo nivel. En la práctica, estas herramientas empiezan a ser importantes cuando el problema empresarial ya no es sólo "ejecutar el modelo" sino "ejecutar el modelo de manera eficiente en el hardware que realmente podemos comprar, implementar y mantener". Esa distinción parece pequeña en una reunión y se vuelve muy grande en un presupuesto.
TensorFlow Lite representa otro temperamento completamente diferente. Es la voz de la moderación. En dispositivos periféricos, objetivos móviles y sistemas con recursos limitados, la integridad suele ser menos valiosa que la idoneidad. Los ingenieros no necesitan una estructura majestuosa allí; necesitan un modelo que cargue, ejecute y se mantenga dentro de estrictas limitaciones de memoria, tamaño del paquete, uso de energía y tiempo de inicio. TensorFlow Lite tiene sentido cuando el objetivo de implementación en sí es la fuerza principal que da forma a la arquitectura. El contraejemplo también es común: un equipo comienza con un tiempo de ejecución de borde porque parece eficiente, luego lo amplía lentamente hacia una plataforma de servidor más amplia o un flujo de trabajo con necesidades más dinámicas de las que fue diseñado para soportar. La eficiencia en el límite no se traduce automáticamente en comodidad en cualquier otro lugar.
Luego está llama.cpp, que merece especial atención porque cambió el mapa emocional de la inferencia local. Antes de que llama.cpp y proyectos similares se generalizaran, muchos ingenieros asumieron que el servicio de modelos de lenguaje grande local seguiría siendo un juguete de investigación o un dispositivo empresarial. llama.cpp demostró algo más interesante: con una cuantificación agresiva, un trabajo cuidadoso del núcleo y una ingeniería disciplinada, un LLM moderno podría convertirse en un componente nativo local dentro de los sistemas ordinarios. Esa visión importa más allá de un proyecto. Recordó a todo el campo que la ejecución nativa, la compresión de modelos y la implementación práctica pueden avanzar mucho más rápido de lo que suelen sugerir las narrativas centralizadas. Pero llama.cpp también tiene un límite natural. Es excelente cuando el trabajo consiste en ejecutar modelos de transformadores compatibles de forma local y eficiente. No es un sustituto general de todo el ecosistema de aprendizaje profundo, y los equipos se meten en problemas cuando le piden que se convierta en uno.
Cómo elegir sin dejarse seducir por las exageraciones
La forma más confiable de elegir entre estas bibliotecas es comenzar con el producto y luego nombrar la herramienta. Empiece por preguntar qué posee realmente su aplicación y qué simplemente consume. Si el sistema consume principalmente un modelo estable y necesita una inferencia portátil y bien delimitada, ONNX Runtime suele ser la respuesta más tranquila. Si el sistema en sí debe hablar en el lenguaje de tensores, módulos y semántica de marcos, LibTorch merece la discusión. Si la parte difícil es la eficiencia de la CPU, la optimización de gráficos o la implementación de Intel, oneDNN y OpenVINO se acercan al centro. Si el objetivo es pequeño, está fuera de línea, es sensible a la batería o está integrado, TensorFlow Lite se vuelve más natural. Si el producto trata explícitamente de ejecutar un modelo de lenguaje cuantificado local en un entorno nativo, llama.cpp debe estar en la mesa desde el principio.
Una segunda pregunta es igualmente importante: ¿dónde se pagará realmente el trabajo de ingeniería? Los equipos a menudo eligen bibliotecas según los titulares de las pruebas comparativas y luego descubren que su verdadero problema está en otra parte. Un tiempo de ejecución con cifras de rendimiento espectaculares aún puede no ser la opción adecuada si la exportación es inestable, el preprocesamiento es complicado o el paquete de implementación se vuelve frágil. Un tiempo de ejecución algo más lento puede seguir siendo la mejor opción empresarial si crea una frontera más clara entre los productores de modelos y los mantenedores del sistema. Los ingenieros que han lanzado más de un producto de IA aprenden profundamente esta lección: la mejor biblioteca no siempre es la que gana el gráfico de referencia, sino la que hace que sea más fácil razonar sobre todo el sistema a las dos de la mañana.
Aquí es donde los contraejemplos se vuelven saludables. Considere un equipo que crea un servicio de análisis de documentos nativo. La opción más moderna podría ser optar por la estructura más pesada disponible, porque parece preparada para el futuro. Pero si el modelo es estático, el proceso de preprocesamiento es sencillo y la necesidad real es una inferencia estable dentro de un servicio C++ existente, es probable que ONNX Runtime genere menos resistencia a largo plazo. Consideremos ahora lo contrario. Un equipo está realizando experimentación nativa con flujos tensoriales personalizados, cambios frecuentes de arquitectura y un estrecho acoplamiento con la lógica de entrenamiento basada en PyTorch. Forzar todo a través de ONNX porque suena "listo para producción" puede crear un flujo de trabajo frágil centrado en la exportación que nadie realmente disfruta. En cada caso, el error es el mismo: el equipo eligió una identidad antes de elegir una carga de trabajo.
Cómo se ve realmente una buena integración
Un flujo de trabajo de integración maduro comienza con el contrato de datos, no con la biblioteca. Antes de debatir los tiempos de ejecución, decida qué le da la aplicación al modelo y qué devuelve el modelo a la aplicación. Nombra las formas del tensor, los tipos d, las reglas de normalización, las rutas de tokenización, el comportamiento del relleno, los supuestos de procesamiento por lotes y las condiciones de error. Esto suena casi burocrático, pero es la fuente silenciosa de muchas implementaciones exitosas. Los sistemas fallan no sólo porque los tiempos de ejecución son incorrectos, sino porque los límites que los rodean son confusos.
Una vez que el contrato de datos es estable, la exportación o el empaquetado del modelo se vuelve mucho más fácil de validar. Un equipo puede comparar los resultados entre la ruta de investigación y la ruta de producción bajo insumos representativos, medir tolerancias y detectar dónde se desvía la fidelidad. Aquí los ingenieros descubren si su elegante arquitectura sobrevive a la realidad. A veces, el gráfico exportado está bien y el único problema es que el preprocesamiento no coincide. A veces, el tiempo de ejecución es perfecto y el verdadero problema es la sobresuscripción de subprocesos en otras partes del servicio. A veces, un modelo supuestamente pequeño no puede sobrevivir a la presión de la memoria de la concurrencia real. Cada uno de estos descubrimientos es útil. Significa que el sistema ha comenzado a hacerse visible.
Después viene la evaluación comparativa y la elaboración de perfiles, y aquí se aplica la misma vieja regla: mide el sistema que pretendes enviar, no el juguete que solías sentirte inteligente. Compare el modelo bajo formas de solicitud, tamaños de lote, variabilidad de entrada y condiciones de hardware realistas. También preprocesamiento y posprocesamiento de perfiles, porque muchos equipos inconscientemente comparan solo el núcleo del modelo y olvidan que los clientes pagan por todo el camino. En la IA de producción, un gráfico de diez milisegundos rodeado por sesenta milisegundos de pegamento evitable sigue siendo una característica de setenta milisegundos.
Finalmente, haga que la implementación sea reproducible. Las pilas de IA nativas recompensan la disciplina. Anclar versiones, compilador de documentos y supuestos de tiempo de ejecución, decidir qué proveedores de ejecución o características de CPU se requieren y mantener un conjunto limitado de configuraciones admitidas. Si un compañero de equipo no puede reproducir la misma ruta de inferencia en otra máquina sin arqueología, la pila no está lista, por muy impresionante que haya sido la demostración. Una buena ingeniería de IA en C++ no se trata solo de velocidad. Se trata de lograr que el sistema se calme lo suficiente como para que la velocidad siga siendo comprensible.
Errores que se siguen repitiendo
El error más común es confundir la verdad de la investigación con la verdad de la producción. Un modelo que se ve excelente en un cuaderno puede volverse incómodo una vez exportado, cuantificado, integrado, observado y ejecutado en concurrencia real. Eso no significa que el modelo fuera malo. Significa que el sistema era más grande que el experimento. El segundo error recurrente es pretender que el preprocesamiento y el posprocesamiento son secundarios. En productos reales, suelen suponer la mitad del trabajo. La política de cambio de tamaño de imagen, el comportamiento del tokenizador, la normalización de funciones, los umbrales de calibración y la decodificación de salida tienen la misma precisión y latencia que el tiempo de ejecución central.
Un tercer error es comprometerse demasiado con un marco porque parece moderno o integral. A veces, los ingenieros seleccionan la herramienta más grande posible anticipándose a necesidades que nunca llegan. Luego, el producto paga por capacidades que no utiliza. También existe el error opuesto: elegir el tiempo de ejecución más liviano en nombre de la pureza y luego descubrir que el comportamiento dinámico, las operaciones personalizadas o la semántica a nivel de marco no eran opcionales después de todo. La sabiduría reside en pagar sólo por el poder que realmente puedes explicar.
También hay un fallo de actitud más sutil. Algunos equipos tratan la elección de la biblioteca como si resolviera toda la historia de la ingeniería. No es así. Los buenos resultados provienen de un trabajo humilde y repetido: validar resultados, medir rutas activas, eliminar copias evitables, reducir la fricción de inicio, simplificar el empaquetado y mantener legibles los límites del tiempo de ejecución. Las bibliotecas de código abierto hacen posible este trabajo; no lo realizan en nuestro nombre.
Una pequeña historia de implementación que vale la pena recordar
Imagine un equipo que comienza con un prototipo de visión de Python. La demostración es lo suficientemente sólida como para obtener soporte interno y pronto la conversación gira en torno a la integración con un servicio C++ existente que ya maneja la ingesta de imágenes, la evaluación de reglas y la generación de informes. El equipo tiene varias tentaciones. Una es mantener el modelo detrás de un servicio Python separado para siempre porque es fácil a corto plazo. Otra es trasladar todo a un marco nativo pesado de inmediato porque eso suena serio. Una tercera es pasar semanas discutiendo sobre arquitectura antes de estabilizar incluso el contrato de insumos.
El camino más maduro es más tranquilo. Primero, el equipo define cuidadosamente la semántica de preprocesamiento y salida. Luego prueba la fidelidad de la exportación en imágenes representativas. Elige ONNX Runtime porque el problema es la inferencia estática y no la experimentación basada en el marco. Posteriormente, para una variante de borde con restricciones de hardware más estrictas, evalúa si TensorFlow Lite o una ruta de tiempo de ejecución optimizada más agresivamente tiene sentido para esa rama de producto. Meses más tarde, si la empresa añade una función de asistente local, llama.cpp podría entrar también en la arquitectura, no porque una biblioteca ganara todo el debate, sino porque cada herramienta se ganó su lugar en un rincón diferente del sistema.
Ésa es la lección más profunda detrás de todas estas bibliotecas. La ingeniería seria en IA rara vez premia la pureza. Recompensa el ajuste. La mejor biblioteca de código abierto no es la que tiene más seguidores. Es el que permite que su modelo se convierta en parte de un sistema real sin obligar al resto del sistema a volverse irrazonable.
Laboratorio práctico: cree una pequeña CLI de tiempo de ejecución de ONNX
La teoría se vuelve más convincente cuando se compila.
Construyamos el programa de inferencia nativo útil más pequeño en C++. El objetivo no es entrenar un modelo. El objetivo es sentir, con tus propias manos, cómo se ve un límite de tiempo de ejecución nativo.
Para este ejercicio necesitas:
- un compilador de C++17
- Chacer
- un paquete ONNX Runtime prediseñado de las versiones oficiales
- cualquier modelo pequeño
.onnxcuya entrada sea un tensor flotante plano
Diseño del proyecto
tiny-ort/
CMakeLists.txt
main.cpp
third_party/
onnxruntime/
model.onnx
__CÓDIGO_0__
cmake_minimum_required(VERSION 3.16)
project(tiny_ort LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(ORT_ROOT "${CMAKE_SOURCE_DIR}/third_party/onnxruntime")
add_executable(tiny_ort main.cpp)
target_include_directories(tiny_ort PRIVATE "${ORT_ROOT}/include")
if (WIN32)
target_link_directories(tiny_ort PRIVATE "${ORT_ROOT}/lib")
target_link_libraries(tiny_ort PRIVATE onnxruntime)
else()
target_link_directories(tiny_ort PRIVATE "${ORT_ROOT}/lib")
target_link_libraries(tiny_ort PRIVATE onnxruntime)
endif()
__CÓDIGO_0__
#include <onnxruntime_cxx_api.h>
#include <array>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
Ort::Env env{ORT_LOGGING_LEVEL_WARNING, "tiny-ort"};
Ort::SessionOptions opts;
opts.SetIntraOpNumThreads(1);
opts.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
const ORTCHAR_T* model_path = ORT_TSTR("model.onnx");
Ort::Session session{env, model_path, opts};
std::vector<int64_t> shape{1, 4};
std::vector<float> input{0.25f, 0.50f, 0.75f, 1.0f};
auto mem_info = Ort::MemoryInfo::CreateCpu(
OrtArenaAllocator,
OrtMemTypeDefault
);
Ort::Value tensor = Ort::Value::CreateTensor<float>(
mem_info,
input.data(),
input.size(),
shape.data(),
shape.size()
);
const char* input_names[] = {"input"};
const char* output_names[] = {"output"};
auto outputs = session.Run(
Ort::RunOptions{nullptr},
input_names,
&tensor,
1,
output_names,
1
);
float* out = outputs[0].GetTensorMutableData<float>();
auto out_shape = outputs[0].GetTensorTypeAndShapeInfo().GetShape();
auto out_count = std::accumulate(
out_shape.begin(),
out_shape.end(),
int64_t{1},
std::multiplies<int64_t>{}
);
std::cout << "Output values:\n";
for (int64_t i = 0; i < out_count; ++i) {
std::cout << " [" << i << "] = " << out[i] << "\n";
}
return 0;
}
Construir
En Linux o macOS:
cmake -S . -B build
cmake --build build -j
./build/tiny_ort
En Windows con MSVC:
cmake -S . -B build
cmake --build build --config Release
.\build\Release\tiny_ort.exe
Lo que esto te enseña
Este pequeño proyecto ya te obliga a afrontar varias realidades de producción:
- donde vive el tiempo de ejecución
- cómo se empaquetan las dependencias nativas
- qué nombres y formas de tensores son realmente
- cómo se siente el manejo explícito de la memoria en un límite de inferencia nativo
Ese es exactamente el punto. Una biblioteca deja de ser un término de marketing y se convierte en una elección de ingeniería.
Tareas de prueba para entusiastas
Si desea convertir el artículo en un laboratorio de fin de semana, estos son los siguientes pasos útiles:
- Reemplace el vector de entrada codificado con valores cargados desde un archivo de texto pequeño o binario.
- Imprima dinámicamente formas tensoriales de entrada y salida en lugar de asumirlas.
- Agregue una medición de latencia simple alrededor de
session.Runy compare los subprocesos intraoperatorios1,2y4. - Cambie ONNX Runtime por LibTorch en una aplicación de inferencia de juguetes similar y escriba lo que se volvió más fácil y lo que se volvió más pesado.
- Exporte un modelo pequeño desde Python, cárguelo en este programa C++ y verifique que las diferencias de preprocesamiento no cambien silenciosamente el resultado.
Si realiza esas cinco tareas con honestidad, comprenderá más sobre la implementación de la IA que muchas personas que pueden recitar nombres de marcos durante una hora.
Resumen
Las bibliotecas de redes neuronales de código abierto para C++ no marchan en un solo desfile. Surgieron de diferentes necesidades de ingeniería y siguen siendo más útiles cuando respetamos esos orígenes. ONNX Runtime es poderoso porque reduce el problema y brinda a los equipos de producción un límite de inferencia estable. LibTorch es valioso cuando la aplicación nativa realmente necesita pensar en tensores y módulos en lugar de simplemente consumir un gráfico congelado. oneDNN y OpenVINO son importantes cuando la eficiencia de bajo nivel y la implementación en familias de hardware específicas dejan de ser preocupaciones secundarias. TensorFlow Lite brilla cuando el dispositivo en sí es la restricción estricta. llama.cpp es importante porque demostró, muy públicamente, que una ingeniería nativa cuidadosa puede convertir modelos de lenguajes modernos en componentes locales prácticos en lugar de servicios distantes.
Por lo tanto, la mejor elección rara vez es la más moderna. Es el que hace que todo el sistema esté más tranquilo. Un buen tiempo de ejecución es un tiempo de ejecución que su equipo puede comprender, comparar, perfilar, empaquetar, probar y operar sin mitología. Cuando los ingenieros eligen desde ese lugar, la IA de código abierto deja de parecer un zoológico confuso de marcos y comienza a verse como lo que realmente es: una caja de herramientas lo suficientemente rica como para soportar productos nativos serios.
Referencias
- API de tiempo de ejecución de ONNX C/C++: https://onnxruntime.ai/docs/api/c/index.html
- Proyecto oficial de ONNX: https://onnx.ai/
- Documentación de la interfaz de PyTorch C++: https://docs.pytorch.org/cppdocs/frontend.html
- Documentación oficial de oneDNN: https://uxlfoundation.github.io/oneDNN/
- Documentación de OpenVINO: https://docs.openvino.ai/
- Documentos de la API de LiteRT/TensorFlow Lite C++: https://ai.google.dev/edge/litert/api_docs/cc
- Repositorio llama.cpp: https://github.com/ggml-org/llama.cpp
- Repositorio ONNX Runtime GitHub: https://github.com/microsoft/onnxruntime
- Repositorio de PyTorch: https://github.com/pytorch/pytorch