Inferensys

Glossary

Compute Graph

A compute graph is a directed acyclic graph (DAG) representation of a neural network where nodes are operations and edges are data tensors, used for optimization and scheduling.
Enterprise console with connected nodes and monitoring panels for orchestrated systems.
TINYML DEPLOYMENT

What is a Compute Graph?

A compute graph is the fundamental data structure used by frameworks like TensorFlow and PyTorch to represent and optimize machine learning models for execution, especially on constrained hardware.

A compute graph is a directed acyclic graph (DAG) representation of a computational workflow, where nodes represent operations (ops) and edges represent the multidimensional data arrays (tensors) flowing between them. In machine learning, it explicitly defines the sequence of mathematical transformations from model input to output. This graph-based abstraction is crucial for frameworks to perform static scheduling, operator fusion, and memory optimization before runtime, enabling efficient deployment on microcontrollers.

For microcontroller inference optimization, the compute graph is analyzed and transformed by a compiler (e.g., TensorFlow Lite Micro). The compiler performs hardware-aware optimizations like fusing a convolution, batch norm, and ReLU activation into a single kernel, and it performs static memory allocation for all tensors. This process minimizes the RAM footprint and flash footprint, eliminates runtime overhead, and produces a deterministic, executable program tailored for the target's fixed-point arithmetic or INT8 inference capabilities.

MICROCONTROLLER INFERENCE OPTIMIZATION

Key Components of a Compute Graph

A compute graph is the fundamental data structure used by inference engines to represent, optimize, and execute a neural network. For microcontroller deployment, its components are heavily optimized for memory, determinism, and speed.

01

Nodes (Operations)

Nodes represent the atomic computational operations (ops) within the neural network. In a microcontroller-optimized graph, these are low-level kernels like:

  • Convolution (CONV2D)
  • Fully Connected (FULLY_CONNECTED)
  • Depthwise Convolution (DEPTHWISE_CONV2D)
  • Pooling (AVERAGE_POOL_2D, MAX_POOL_2D)
  • Activation functions (RELU, RELU6) Each node is implemented as a highly optimized function (kernel) for the target MCU architecture, often using CMSIS-NN libraries or hand-tuned assembly.
02

Edges (Tensors)

Edges are the directed connections between nodes and represent the multidimensional data arrays (tensors) that flow through the graph. For TinyML, tensor characteristics are critical:

  • Data Type: Typically INT8 or INT16 after quantization.
  • Shape: Fixed dimensions (e.g., [1, 32, 32, 3] for an image) determined at compile-time.
  • Memory Lifetime: Each tensor's allocation is analyzed for static memory planning, allowing buffers to be reused (in-place computation) to minimize peak RAM footprint.
03

Static Scheduler

The component that determines the deterministic execution order of all nodes and pre-assigns all tensor memory buffers at compile-time. This eliminates runtime allocation overhead and memory fragmentation. Key features include:

  • Operator Fusion: Combines sequences like Conv -> BatchNorm -> Activation into a single fused kernel node.
  • Memory Planning: Performs a liveness analysis to overlap tensor lifetimes, allowing a single memory buffer to be reused for multiple, non-concurrent tensors, drastically reducing peak RAM usage.
04

Quantization Parameters

For integer-only inference, the graph stores the quantization metadata for each tensor edge. This is not the tensor data itself, but the constants needed to convert between integer and real-valued domains:

  • Scale (float): The multiplier used in dequantization: real_value = integer_value * scale.
  • Zero-Point (int): Used in asymmetric quantization schemes. The integer value that corresponds to the real value zero. These parameters are embedded as constants in the graph, enabling efficient integer-only arithmetic without floating-point hardware.
05

Subgraphs & Delegates

A mechanism to partition the compute graph for heterogeneous execution. A subgraph is a set of nodes that can be offloaded to a specialized hardware accelerator (e.g., an NPU or DSP). A delegate is the software interface that handles execution of that subgraph. This allows parts of the model (like heavy convolutions) to run on dedicated silicon while the rest executes on the main CPU core, optimizing for both performance and power.

06

Metadata & Execution Context

The minimal runtime state required to execute the graph. This is separate from the tensor buffers and includes:

  • Pointer to the model's weight array in flash memory.
  • Pre-allocated tensor arena: A single, contiguous block of RAM serving as the memory pool for all activation buffers.
  • Node execution list: A simple, sequential list of function pointers and buffer indices, generated by the static scheduler, that the lightweight interpreter loops over. This context is typically less than 1KB in size.
MICROCONTROLLER INFERENCE OPTIMIZATION

Compute Graph Optimization for TinyML

Compute graph optimization transforms a neural network's abstract representation into an execution plan tailored for the severe memory, power, and compute constraints of microcontrollers.

A compute graph is a directed acyclic graph (DAG) representation of a neural network where nodes represent operations (ops) and edges represent the multidimensional data arrays (tensors) flowing between them. For TinyML, the primary optimization goal is to transform this abstract graph into a static, memory-efficient execution plan that eliminates runtime overhead. This involves techniques like operator fusion to combine sequential layers, static memory allocation to pre-assign all tensor buffers, and static scheduling to define a deterministic execution order at compile-time.

Further optimizations target the graph's structure and data flow. In-place computation reuses memory buffers by writing a layer's output over its input, drastically reducing peak RAM footprint. The compiler also performs constant folding to pre-compute static operations and dead code elimination to remove unused graph branches. The final optimized graph is often compiled into a flat, sequential C/C++ source file with minimal control logic, enabling efficient execution on microcontrollers without a dynamic runtime.

COMPUTE GRAPH

Framework Implementation

A compute graph is a directed acyclic graph (DAG) representation of a neural network where nodes represent operations (ops) and edges represent the multidimensional data arrays (tensors) flowing between them. This abstract representation is the foundation for optimization and scheduling in deployment frameworks.

01

Graph Construction & Serialization

Frameworks like TensorFlow Lite Micro (TFLM) and proprietary SDKs construct a compute graph from a trained model file (e.g., .tflite). This involves:

  • Parsing the model flatbuffer/protobuf to extract layer definitions.
  • Instantiating node objects for each operation (Conv2D, FullyConnected, etc.).
  • Creating edges based on tensor producer/consumer relationships.
  • Serializing the finalized graph into a format suitable for the microcontroller's memory map, often as a constant C array in flash.
02

Static Scheduling & Memory Planning

For deterministic execution on MCUs, the graph is statically scheduled at compile-time. This process:

  • Determines execution order via a topological sort of the DAG.
  • Performs lifetime analysis on all intermediate tensors (activations).
  • Allocates memory using a static memory planner that overlays tensors with non-overlapping lifetimes into a single, contiguous arena memory buffer. This minimizes peak RAM footprint and eliminates runtime allocation overhead and fragmentation.
03

Operator Registration & Kernel Dispatch

The framework maintains a registry mapping operation types (e.g., kTfLiteConv2D) to optimized kernel functions. During inference:

  • The interpreter traverses the scheduled node list.
  • For each node, it looks up the appropriate kernel in the registry.
  • It dispatches execution to the kernel, passing pointers to the input/output tensors in the arena.
  • Kernels are often hand-optimized assembly or CMSIS-NN functions for Arm Cortex-M, leveraging SIMD instructions and fixed-point arithmetic.
04

Optimization Passes

Before final code generation, the graph undergoes transformation passes:

  • Operator Fusion: Combines sequences like Conv2D -> BatchNorm -> ReLU into a single, fused node to reduce intermediate writes and kernel call overhead.
  • Constant Folding: Pre-computes operations on constant tensors (e.g., reshapes) at compile-time.
  • Quantization Embedding: Converts floating-point graph nodes into their integer-quantized equivalents (INT8 inference), embedding scaling factors and zero-points as node metadata.
  • Redundant Node Elimination: Removes no-op nodes like identity operations.
05

Hardware-Aware Partitioning

For systems with heterogeneous cores (e.g., MCU + a tiny NPU), the graph can be partitioned. A compiler analyzes the graph and:

  • Labels nodes for execution on specific hardware units (CPU, NPU, DSP).
  • Inserts memory transfer operations at partition boundaries to move tensors between memory regions accessible to different cores.
  • This requires detailed cost models for communication latency and core capabilities to maximize throughput.
06

Toolchain Integration (Build & Link)

The final implementation integrates tightly with the MCU toolchain:

  • The optimized graph and kernels are compiled into a static library.
  • The linker script reserves specific sections in flash for the model parameters (.rodata.tensor) and in RAM for the arena (.bss.tensor_arena).
  • The application code includes a header file exposing a simple Invoke() API, which calls into the graph interpreter. This creates a standalone, static binary with no external dependencies for deployment.
COMPILATION STRATEGY

Static vs. Dynamic Compute Graphs

A comparison of the two primary strategies for representing and executing neural network operations, focusing on their implications for microcontroller deployment.

FeatureStatic GraphDynamic Graph

Graph Definition

Fixed at compile/convert time.

Constructed at runtime.

Representative Frameworks

TensorFlow Lite Micro, CMSIS-NN

PyTorch (eager mode), MicroPython interpreters

Memory Allocation

Static (deterministic, compile-time).

Dynamic (on-the-fly, can cause fragmentation).

Runtime Overhead

Very low (no graph construction logic).

Higher (includes graph building & optimization).

Optimization Scope

Whole-model, ahead-of-time (AOT).

Per-operation or subgraph, just-in-time (JIT).

Model Flexibility

Low. Model architecture is fixed after compilation.

High. Model structure can change based on input data.

Peak RAM Footprint

Predictable and minimized via static scheduling.

Variable and typically higher due to allocation overhead.

Debugging & Introspection

Challenging; requires offline analysis tools.

Easier; runtime graph can be inspected.

Typical Use Case

Deployment of fixed models on MCUs (TinyML).

Research, prototyping, or models with dynamic control flow.

COMPUTE GRAPH

Frequently Asked Questions

A compute graph is the fundamental data structure for representing and optimizing neural network execution, especially critical for resource-constrained microcontroller deployment.

A compute graph is a directed acyclic graph (DAG) representation of a neural network where nodes represent operations (ops) and edges represent the multidimensional data arrays (tensors) flowing between them. It serves as an intermediate representation (IR) between a high-level model definition (e.g., from TensorFlow or PyTorch) and the low-level, optimized code executed on a target device. For TinyML, this graph is the blueprint that specialized compilers analyze to apply critical optimizations like operator fusion, static memory allocation, and kernel selection to fit within the severe memory and compute constraints of a microcontroller.

Prasad Kumkar

About the author

Prasad Kumkar

CEO & MD, Inference Systems

Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.

His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.