Implementation:Onnx Onnx IR Graph Model
| Knowledge Sources | |
|---|---|
| Domains | Intermediate Representation, Graph Data Structure, Core Infrastructure |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
Defines the core intermediate representation (IR) data structures for ONNX graphs, including the Graph, Node, Value, and Attributes types that form the in-memory representation of ONNX models.
Description
The ir.h header is the absolute core of ONNX's C++ implementation. It defines the complete in-memory graph representation used for model construction, analysis, optimization, and transformation. The design centers on three interconnected structures:
Value represents data flowing between nodes in the graph. Each Value carries type metadata (elem_type_), optional shape information (sizes_ as a vector of Dimension objects), a unique name for identification, and a full TypeProto for complex types. Values track their consumer nodes via a use_list (vector of Use structs), enabling efficient graph traversal and transformation operations like replaceAllUsesWith.
Node represents a single computation operation. It inherits from Attributes<Node> using CRTP (Curiously Recurring Template Pattern) to enable method chaining. Each Node stores its kind (operator type as a Symbol), input/output Values, owning Graph pointer, and optional metadata (name, domain, doc_string, overload). Nodes are linked in a doubly-linked list (next_in_graph array) that maintains topological ordering. Key operations include addInput, replaceInput, insertBefore/insertAfter, and destroy.
Graph owns all Nodes and Values, managing their lifetimes via unordered_set containers. It uses sentinel nodes for the input (kParam), output (kReturn), and standalone initializers (initializer_node_). The Graph provides factory methods (create, appendNode), initializer management, graph traversal (forSelfAndEachSubGraph, forEachNode), and unique name generation.
The Attributes template provides a generic attribute storage mechanism supporting 12 attribute kinds: float, floats, int, ints, string, strings, tensor, tensors, graph, graphs, type_proto, type_protos. The CREATE_ACCESSOR macro generates typed getter/setter pairs for each kind. Attributes are stored in a vector for deterministic ordering with O(n) lookup.
Supporting types include Dimension (representing known integer, symbolic parameter, or unknown dimensions), OpSetID (domain + version pair with string serialization), ResourceGuard (RAII scope guard), and AttributeValue hierarchy (ScalarAttributeValue and VectorAttributeValue templates).
Usage
This header is included by virtually every C++ file in the ONNX project that needs to manipulate graph structures. It is essential for model loading (ir_pb_converter.cc), optimization passes, shape inference, validation, version conversion, and Python binding export. The structures are designed for in-place mutation rather than immutable transformation, favoring performance in optimization workloads.
Code Reference
Source Location
- Repository: Onnx_Onnx
- File: onnx/common/ir.h
- Lines: 1-1448
Signature
namespace ONNX_NAMESPACE {
struct Dimension final {
Dimension();
explicit Dimension(std::string param);
explicit Dimension(int64_t dim);
bool is_unknown;
bool is_int;
int64_t dim;
std::string param;
};
enum class AttributeKind : uint8_t { f, fs, i, is, s, ss, t, ts, g, gs, tp, tps };
struct Value final {
Value* setElemType(int32_t elem_type);
Value* setSizes(std::vector<Dimension> sizes);
Value* setUniqueName(const std::string& name, bool update_related_names = true);
void replaceAllUsesWith(Value* newValue);
use_list uses() const;
};
struct Node : public Attributes<Node> {
NodeKind kind() const;
ArrayRef<Value*> inputs();
ArrayRef<Value*> outputs();
Value* addInput(Value* node);
Value* addOutput();
Node* insertBefore(Node* n);
Node* insertAfter(Node* n);
void destroy();
};
class OpSetID final {
static OpSetID fromString(const std::string& target);
std::string toString() const;
const std::string& domain() const;
int64_t version() const;
};
struct Graph final {
Graph();
ArrayRef<Value*> inputs();
ArrayRef<Value*> outputs();
graph_node_list nodes();
Node* create(NodeKind kind, size_t num_outputs = 1);
Node* appendNode(Node* n);
Value* addInput();
void addInitializer(Tensor& initializer);
Value* addInitializerAndCreateValue(Tensor& initializer);
void forEachNode(const std::function<void(Node*)>& fn);
};
} // namespace ONNX_NAMESPACE
Import
#include "onnx/common/ir.h"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| kind | NodeKind (Symbol) | Yes | Operator type symbol when creating a Node |
| num_outputs | size_t | No | Number of output Values for a new Node (default: 1) |
| inputs | ArrayRef<Value*> | No | Input Values when creating a Node with inputs |
| initializer | Tensor& | Yes (for addInitializer) | Tensor data for graph initializers |
| name | std::string | No | Unique name for Values and Graphs |
Outputs
| Name | Type | Description |
|---|---|---|
| Graph | std::unique_ptr<Graph> | Complete in-memory graph representation |
| Node* | Node pointer | Created node, registered in the graph |
| Value* | Value pointer | Data flow value with type/shape metadata |
| use_list | std::vector<Use> | List of all consumers of a Value |
Usage Examples
#include "onnx/common/ir.h"
using namespace ONNX_NAMESPACE;
// Create a new graph
Graph g;
// Add graph inputs
Value* x = g.addInput();
x->setUniqueName("X");
x->setElemType(TensorProto_DataType_FLOAT);
x->setSizes({Dimension(1), Dimension(3), Dimension(224), Dimension(224)});
// Create a Relu node
Node* relu = g.create(Symbol("Relu"), 1);
relu->addInput(x);
g.appendNode(relu);
// Register the output
g.registerOutput(relu->output());
// Iterate over all nodes
for (Node* n : g.nodes()) {
std::cout << n->kind().toString() << std::endl;
}
// Add an initializer
Tensor weight;
weight.setName("weight");
g.addInitializerAndInput(weight, "weight");
Related Pages
- onnx/common/ir_pb_converter.cc - Converts between protobuf and IR representation
- onnx/common/graph_node_list.h - Intrusive doubly-linked list iterators for Node traversal
- onnx/common/tensor.h - Tensor data container used by initializers
- onnx/common/interned_strings.h - Symbol interning for NodeKind identifiers
- onnx/common/assertions.h - ONNX_ASSERT macros for invariant checking