How the C++ libraries are split#
onnx-light is intentionally split into several small static (or shared)
C++ libraries (also referred to as assemblies) instead of a single
monolithic archive. The goal is to let any C++ project link only
what it actually needs: a program that just parses a ModelProto does
not need operator schemas, a program that only registers schemas does
not need shape inference, a program that only evaluates models does not
need the full ONNX schema / checker stack, and so on.
Each library has a well defined responsibility and a minimal set of
dependencies on the other libraries. The full dependency graph is
shown below (arrows point from a library to the library it depends
on). The SVG below is generated from
library_split.dot with
dot -Tsvg (Graphviz); regenerate it after editing the .dot source.
The same graph as an ASCII tree (rooted at lib_onnx_proto, the
base dependency):
lib_onnx_proto
└── lib_onnx_core
├── lib_onnx_op
├── lib_onnx_shape
├── lib_onnx_patterns
├── lib_onnx_kernels
│ └── lib_onnx_backend_test
├── lib_onnx_gradient
└── lib_onnx_manipulations
└── lib_onnx_lib
lib_onnx_core is a lightweight intermediate library that sits
between lib_onnx_proto and all higher-level libraries. It owns the
graph-node input helpers (CollectExternalInputs, CollectNodeInputs,
CollectRemainingInputs), the symbolic dimension-expression library
(onnx_core/expressions/expressions.h), and the LightOpSchema
operator-schema data structures (onnx_core/light_op_schema/light_op_schema.h)
so that lib_onnx_op (operator schemas),
lib_onnx_manipulations, lib_onnx_shape (shape inference), and
lib_onnx_kernels (reference kernels) can share them without any of
them depending on each other. The TensorType enumeration and the
ToTypeString converter live one level lower, in lib_onnx_proto
(onnx_proto/type_helper.h), so that lib_onnx_core itself can use
them.
lib_onnx_op, lib_onnx_manipulations, lib_onnx_shape,
lib_onnx_patterns, and lib_onnx_kernels are siblings that each depend
on lib_onnx_core
(and transitively on lib_onnx_proto). lib_onnx_shape depends on
lib_onnx_core only (it does not pull in lib_onnx_op or
lib_onnx_lib). lib_onnx_kernels depends on lib_onnx_core
only (it does not pull in lib_onnx_manipulations).
lib_onnx_manipulations gathers the schema-independent
ModelProto manipulation helpers (text parser / printer, attribute and
tensor proto helpers, data-type name utilities); lib_onnx_lib (full
schemas, checker, shape inference, version converter) depends publicly
on it.
lib_onnx_backend_test depends publicly on lib_onnx_kernels (and
transitively on lib_onnx_core / lib_onnx_proto) because every
registered test case computes its expected outputs by invoking the
bundled C++ reference kernels.
lib_onnx_gradient provides reverse-mode automatic differentiation for
ONNX graphs (GradientOfNodes / GradientOfFunction); it depends on
lib_onnx_core only (and transitively on lib_onnx_proto). Like
lib_onnx_kernels and lib_onnx_backend_test it belongs to the
extended build variant and is only built when
ONNX_LIGHT_BUILD_KERNELS=ON.
Core/extension registration pattern (examples)#
The same design pattern is reused across shape inference, peak-memory
estimation, kernels, backend tests, and operator schemas:
onnx_core defines the generic types / registries / dispatch APIs, while
the concrete ONNX operator implementations live in sibling libraries
(onnx_extensions and onnx_op) and are wired in explicitly.
Feature |
Core side (mechanism only) |
Extension side (concrete implementations) |
|---|---|---|
Shape inference |
|
|
Peak memory |
|
|
Runtime kernels |
|
|
Graph optimization patterns |
|
|
Backend tests |
|
|
Light operator schema |
|
|
For the first four rows above, explicit registration keeps onnx_core
independent from the extension libraries:
// shape inference + peak memory
onnx_shapes::RegisterShapeFunctions();
onnx_shapes::RegisterPeakMemoryFunctions();
// runtime kernels
onnx_kernels::RegisterKernelFunctions();
// graph optimization patterns
onnx_patterns::RegisterPatterns();
This means a downstream binary can keep linking minimal. If it never calls shape inference, peak-memory estimation, runtime execution, graph-pattern registration, or backend-test collection, it does not need to link the corresponding extension library.
When installed (cmake --install) all libraries are exported under the
onnx_light:: namespace and can be consumed individually through
find_package(onnx_light).
Summary of each library#
Library / CMake target and Sources |
What it contains |
|---|---|
|
Protobuf-compatible message types ( |
|
Intermediate library that sits between |
|
Lightweight |
|
Foundational |
|
Full ONNX-compatible operator schemas (with history), checker,
inliner, shape inference and version converter. This is the
target to link for the complete ONNX-light experience.
Depends publicly on |
|
Shape-inference dispatch table, expression engine for small
tensor / backward-propagation shape inference, and graph
optimization helpers. Depends publicly on |
|
Concrete ONNX graph-rewriting patterns and the explicit
|
|
C++ reference implementation of the ONNX operators used to
evaluate models in-process. Contains the runtime data model
( |
|
Backend test infrastructure ( |
|
Reverse-mode automatic differentiation for ONNX graphs. Provides
|
What to link for a given use case#
The libraries are designed so that a downstream project links the smallest set that covers its needs. The most common scenarios are:
Read / write ONNX models, including > 2 GB files, external data or encrypted models, without any operator notion — link
onnx_light::lib_onnx_proto.Enumerate or look up ONNX operator schemas (for example to drive code generation or to validate node op types) without paying for shape inference — link
onnx_light::lib_onnx_op.Parse / print ONNX text models and manipulate ``ModelProto`` / ``GraphProto`` (attribute and tensor proto helpers, data-type name utilities, graph-input collection) without pulling in the operator schemas — link
onnx_light::lib_onnx_manipulations.Full ONNX feature set (schemas with history, checker, inliner, shape inference, version conversion) — link
onnx_light::lib_onnx_lib.Shape inference — link
onnx_light::lib_onnx_shape(which transitively pullslib_onnx_coreandlib_onnx_proto).Use the standard graph-rewriting patterns — link
onnx_light::lib_onnx_patternsand callonnx_patterns::RegisterPatterns()before creating the registered pattern instances. Custom-only optimizers can linklib_onnx_coreand either pass patterns directly toGraphGraphor callcore::builder::RegisterPattern. See Registering and selecting graph patterns for complete selection, registration, and linking examples.Evaluate ONNX nodes / graphs / models in C++ using the bundled reference kernels (runtime
struct Tensor,RunGraph/RunFunction/RunModel,SplitMix64RNG, …) without pulling in any backend-test fixtures — linkonnx_light::lib_onnx_kernels.Run backend tests / evaluate models in C++ using the built-in reference kernels — link
onnx_light::lib_onnx_backend_test(which transitively pullslib_onnx_kernels,lib_onnx_coreandlib_onnx_proto). It can be combined withonnx_light::lib_onnx_libwhen both schema validation and execution are needed.Compute gradient functions (reverse-mode automatic differentiation of ONNX graphs) — link
onnx_light::lib_onnx_gradient(which transitively pullslib_onnx_coreandlib_onnx_proto).
The Python extensions follow the same split and each link to the
minimal C++ library that provides their feature. See
Linking onnx-light in C++ for the full discussion of the Python /
C++ packaging and of the shared lib_onnx_proto runtime.