Inferensys

Glossary

Graph Partitioning

Graph partitioning is a compiler optimization that splits a neural network's computational graph into subgraphs for parallel execution across multiple processors, accelerators, or devices to improve throughput and reduce latency.
Performance engineer optimizing AI latency on laptop, latency charts visible, technical optimization session.
COMPUTE GRAPH OPTIMIZATION

What is Graph Partitioning?

A core compiler optimization for parallel and distributed execution of neural networks.

Graph partitioning is the process of dividing a large computational graph into smaller, connected subgraphs that can be executed in parallel across multiple processors, accelerators, or devices. The primary goal is to balance computational load and minimize communication overhead between partitions to improve overall throughput and reduce inference latency. This optimization is critical for deploying models on heterogeneous systems containing CPUs, GPUs, and specialized NPUs.

Effective partitioning requires analyzing the graph's operator dependencies and tensor data flow to make cuts that minimize inter-device communication, which is often a performance bottleneck. Strategies include edge-cut and vertex-cut approaches, guided by a cost model that estimates compute and communication costs. The result enables efficient model parallelism and is foundational for frameworks using a hardware delegate architecture to offload subgraphs to specific accelerators.

COMPUTE GRAPH OPTIMIZATION

Key Objectives of Graph Partitioning

Graph partitioning is a critical compiler optimization that divides a neural network's computational graph into subgraphs for parallel or distributed execution. Its primary goals are to maximize hardware utilization and minimize communication overhead.

01

Load Balancing

The primary objective is to distribute computational work evenly across available processors or devices. An imbalanced partition leaves some units idle while others are overloaded, creating a bottleneck.

  • Goal: Minimize the makespan (total execution time) of the slowest partition.
  • Challenge: Operations have varying FLOP costs and memory footprints.
  • Example: Partitioning a Vision Transformer across 4 GPUs requires balancing the compute-heavy self-attention layers, not just splitting layers evenly.
02

Minimize Inter-Partition Communication

Partitions must exchange data across boundaries. This communication is expensive in terms of latency and bandwidth.

  • Goal: Minimize the edge cut—the number or volume of tensors passed between partitions.
  • Strategy: Use algorithms like Kernighan–Lin or METIS that cut few edges.
  • Impact: High communication can negate parallel speedup, adhering to Amdahl's Law. Fusing adjacent operators before partitioning is a common tactic to reduce edges.
03

Hardware-Aware Partitioning

Partitions must respect the capabilities and constraints of the target hardware. This is not a purely mathematical graph problem.

  • Constraints: Memory capacity per device, supported data types (e.g., INT8), and specialized accelerator support (e.g., NPU-compatible ops).
  • Strategy: A cost model estimates latency for a subgraph on a specific device. The partitioner assigns subgraphs to the hardware where they execute fastest.
  • Example: Offloading convolutional layers to a DSP while running element-wise ops on a CPU.
04

Enable Pipeline Parallelism

For models too large for data parallelism, partitioning enables pipeline parallelism, where different stages of the model run concurrently on different devices.

  • Mechanism: The graph is split at layer boundaries. While Device 2 processes micro-batch N, Device 1 processes micro-batch N+1.
  • Challenge: Avoiding pipeline bubbles (idle time) requires careful scheduling (e.g., 1F1B schedule).
  • Use Case: Essential for large language model inference, splitting transformer blocks across multiple devices.
05

Facilitate Model Parallelism

When a single layer's parameters exceed a device's memory, model parallelism splits the layer itself across devices. Graph partitioning identifies these intra-layer split points.

  • Tensor Parallelism: Splits weight matrices (e.g., in a feed-forward layer) across devices, requiring all-reduce communication after the operation.
  • Example: A 120B parameter dense layer is split across 8 GPUs, each holding 15B parameters. The partitioner must insert the correct communication collectives.
06

Optimize for Data Locality

Grouping operations that reuse the same data into the same partition improves cache hit rates and reduces expensive DRAM accesses.

  • Principle: Follows the same logic as loop tiling in traditional compilers.
  • Benefit: Especially critical for memory-bound operations and on devices with complex memory hierarchies (e.g., CPU with L1/L2/L3 cache).
  • Technique: Algorithms that maximize modularity in the graph naturally group tightly-connected operations.
COMPUTE GRAPH OPTIMIZATION

How Graph Partitioning Works

Graph partitioning is a core compiler optimization for parallel and distributed inference, critical for deploying models across multi-core CPUs, GPUs, or edge device clusters.

Graph partitioning is the process of dividing a neural network's computational graph into distinct subgraphs that can be executed concurrently across multiple processors or devices. The primary goal is to maximize parallel execution while minimizing the communication overhead between partitions. Compilers use cost models to estimate the latency and memory footprint of operations, guiding the partitioning algorithm to balance workload and reduce data transfer across device boundaries, which is often the performance bottleneck.

Effective partitioning strategies must account for operator dependencies, hardware heterogeneity, and memory constraints. A partitioner might group computationally intensive layers like convolutions to run on a GPU while placing pre/post-processing on a CPU. Advanced techniques involve profile-guided optimization to make partitioning decisions based on real execution traces. The result is a scheduled execution plan where subgraphs run in parallel, synchronized at specific fusion boundaries, dramatically improving throughput for large models or batch processing.

COMPARISON

Common Graph Partitioning Strategies

A comparison of core strategies for dividing a computational graph across multiple processors or devices, based on their partitioning principle, communication overhead, and hardware targeting.

Partitioning PrincipleCommunication OverheadHardware TargetLoad BalancingImplementation Complexity

Layer-wise (Pipeline Parallelism)

High (sequential dependencies)

Heterogeneous devices (CPU/GPU/NPU)

Difficult (bottleneck on slowest stage)

Moderate

Tensor-wise (Model Parallelism)

Very High (all-to-all for large tensors)

Multi-accelerator nodes (e.g., GPU pods)

Automatic (by parameter size)

High

Operator-level (Data Parallelism)

Low (synchronized gradients/activations)

Homogeneous accelerators

Excellent

Low

Subgraph (Heuristic/Automated)

Medium (optimized by compiler)

Any multi-core/system

Good (via cost model)

Very High

Device-aware (Hardware Delegate)

Minimal (subgraph executed on-device)

Systems with specialized accelerators

N/A (delegate handles subgraph)

Moderate

Input/Output Boundary

Variable (data-dependent)

Streaming pipelines

Dynamic

Low to Moderate

COMPUTE GRAPH OPTIMIZATION

Implementation in ML Frameworks & Runtimes

Graph partitioning is implemented within ML compilers and runtimes to distribute a model's computational workload across multiple processors, accelerators, or devices. This section details the key mechanisms and strategies used in production frameworks.

01

Partitioning by Hardware Capability

Frameworks analyze the computational graph and available hardware to assign subgraphs to the most suitable processor. This involves a cost model that estimates the execution latency of each operator on different backends (e.g., CPU, GPU, NPU).

  • Key Strategy: Operators with high arithmetic intensity (e.g., large matrix multiplications) are assigned to parallel accelerators like GPUs, while control-flow-heavy or memory-bound ops may run on CPUs.
  • Example: In TensorFlow, a Hardware Delegate (e.g., TfLiteGpuDelegate) is responsible for claiming and executing a supported subgraph on the target accelerator.
  • Outcome: Maximizes aggregate hardware utilization and minimizes data transfer between devices.
02

Pipeline Parallelism via Layer Splitting

The graph is partitioned depth-wise, splitting consecutive layers or stages across different devices. This enables pipeline parallelism, where different devices process different micro-batches simultaneously.

  • Mechanism: The framework inserts send and receive operators at partition boundaries to handle inter-device communication.
  • Use Case: Essential for large models that do not fit into the memory of a single device. Each device holds a portion of the model's weights.
  • Framework Example: PyTorch's Pipe API in torch.distributed.pipeline.sync implements this by splitting a nn.Sequential module across GPUs.
03

Tensor Parallelism for Large Layers

Individual weight matrices within a layer (e.g., a linear transformation) are split across multiple devices. Each device computes a portion of the output, requiring a communication step (like an all-reduce) to combine results.

  • Target: Extremely large layers, common in transformer models with multi-billion parameter feed-forward or attention blocks.
  • Implementation: Frameworks like Megatron-LM split the weight matrix of a linear layer along its column or row dimension. The computation Y = XA is distributed by splitting matrix A.
  • Benefit: Allows training and inference of layers whose parameters exceed the memory of a single accelerator.
04

Data Flow Graph Analysis & Cut Finding

The compiler performs a graph traversal (often a topological sort) to analyze data dependencies and find optimal cut points. The goal is to minimize the cost of cross-partition communication while balancing computational load.

  • Algorithm: Uses heuristics or a cost model to evaluate potential partition boundaries. The communication cost is modeled as the size of tensors that must be transferred.
  • Tooling: XLA's partitioner and TVM's relay.transform.PartitionGraph pass perform this analysis, considering user-provided compiler hints (@tvm.register_func) for external code generation.
  • Constraint: Must preserve the original graph's semantic correctness; all producer operations must execute before their consumers.
05

Communication Primitive Insertion

After deciding on partition boundaries, the compiler automatically inserts the necessary communication operators into the graph.

  • Primitives Include: Send/Recv, AllReduce, AllGather, and Broadcast. The choice depends on the parallelism strategy.
  • Location: Inserted at the edges where tensors flow from one partition to another.
  • Optimization: Frameworks may fuse these communication ops with neighboring computation or schedule them asynchronously to overlap communication with computation, hiding latency.
06

Runtime Orchestration & Scheduling

The partitioned subgraphs are managed by a runtime scheduler that handles execution order, synchronization, and memory transfer between devices.

  • Role: Ensures data dependencies across partitions are satisfied. Manages device-specific operator dispatch.
  • Example: TensorFlow's Placer assigns nodes to devices, and its Executor schedules them. For multi-device graphs, the CollectiveOps are scheduled to coordinate communication.
  • Advanced: Some runtimes perform dynamic re-partitioning based on real-time load or input data characteristics, though static partitioning at compile-time is more common for predictability.
GRAPH PARTITIONING

Frequently Asked Questions

Graph partitioning is a critical compiler optimization for distributing a neural network's computational graph across multiple processors or devices. This section answers common technical questions about its mechanisms, goals, and implementation.

Graph partitioning is a compiler optimization technique that divides a neural network's computational graph into smaller, distinct subgraphs that can be executed concurrently across multiple processors, accelerators, or networked devices. The primary goal is to parallelize execution to improve throughput and reduce latency, especially for large models that exceed the memory or compute capacity of a single device. This process is fundamental to distributed inference and training, enabling models to run on heterogeneous hardware clusters. The partitioner must balance computational load, minimize inter-device communication, and respect hardware constraints (e.g., memory limits, supported operators) to create an efficient execution plan.

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.