Tensor compilers that beat hand-tuned libraries on CPUs and GPUs fall apart on deep-learning accelerators, because accelerator constraints make ~95% of their candidate programs invalid and the constraints are too numerous to hand-write (a single GEMM needs 372 of them over 173 variables) — so Heron generates the constraints automatically by static analysis alongside the schedule itself, turning the search space into a formal constraint satisfaction problem, and then explores it with a genetic algorithm that evolves the PROBLEMS rather than the solutions — crossover adds constraints pinning model-identified key variables to parent values, mutation removes one, and a solver samples offspring that are valid by construction — beating four state-of-the-art auto-compilers by 2.71× and vendor hand-tuned libraries by 2.00× on TensorCore, Intel DL Boost, and VTA, at no extra compilation time.
The argument in one glance
-
Problem
Accelerators need libraries faster than humans can write them
Deep-learning accelerators — NVIDIA TensorCore, Intel DL Boost, Google TPU, Cambricon, TVM's VTA — deliver their speedups only through high-performance operator libraries (cuDNN, oneDNN). Writing those by hand demands deep expertise across algorithms, compilers, and microarchitecture, and takes months to years per operator family — falling behind both hardware time-to-market and the weekly churn of model architectures.
-
What people did
Exploration-based compilation
Tensor compilers (AutoTVM, Ansor, AMOS, and polyhedral AKG) reframe code generation as search: a schedule template defines transformations (tiling, fusion, caching, unrolling) with tunable parameters, and a search algorithm — usually a genetic algorithm guided by a learned cost model — hunts the space for fast programs. On CPUs and GPU CUDA cores this matches or beats hand-tuned code.
-
Why it fell short
On accelerators, the space is almost all garbage — and good spaces resist search
DLAs impose constraints general-purpose hardware lacks: TensorCore's matrix unit accepts only m·n·k = 4096 with dims in {8,16,32}, shared memory caps at 48 KB, vector loads at {1,2,4,8}; DL Boost and VTA fix their compute shapes outright. Result — 95% of AutoTVM's candidates for one GEMM are invalid on TensorCore, and its best programs reach 46% of cuDNN on VGG-16 convolutions. Writing accurate constraints by hand is infeasible: characterizing one GEMM's space takes 173 variables and 372 constraints (3D convolution: 861), differing per operator AND per shape, because architectural limits bind tunable parameters only indirectly through products of loop lengths. Worse, even given the constraints, classic search fails: simulated annealing wedges early (only weakly-constrained knobs like unroll can change without invalidating), and genetic crossover on concrete solutions almost never yields valid children — collapsing into random restarts.
-
This paper's idea
Generate the constraints with the schedule; evolve the problems, not the solutions
Heron (Cambricon + ICT/CAS + USTC) makes constraints first-class citizens twice over. GENERATION — as rule-driven static analysis builds the schedule template (tensorize onto hardware intrinsics, insert scratchpad stages, multi-level tiling), companion constraint rules fire on every primitive, emitting six constraint types (PROD, SUM, EQ, LE, IN, SELECT) that tie loop splits, buffer footprints, and intrinsic shapes together into a formal constraint satisfaction problem defining the space. EXPLORATION — the constraint-based genetic algorithm (CGA) performs crossover and mutation on CSPs rather than programs: crossover adds IN-constraints pinning cost-model-identified key variables to one of two parents' values, mutation deletes one such constraint, and a solver samples concrete offspring — valid by construction, with parents' good genes retained. Results across TensorCore, DL Boost, and VTA: 2.71× average over four state-of-the-art auto-compilers, 2.00× over vendor hand-tuned libraries, in 82–87% of competitors' compile time.
Why this problem is worth solving
The economics of accelerators run through software: silicon
that only specialists can program is silicon that ships late
and underperforms in the field. The compiler community’s
answer,
generate-and-search
code generation — a SCHEDULE TEMPLATE lists program
transformations (loop splits, fusion, cache staging, unrolling,
tensorization) whose tunable parameters (tile sizes, unroll
lengths, placement choices) span a space of billions of
concrete programs; a search algorithm with a learned cost
model (typically XGBoost trained on measured samples) hunts
the space, measuring the most promising candidates on real
hardware. TVM’s ecosystem — AutoTVM with manual templates,
Ansor with rule-generated ones — made this the standard for
CPUs and GPUs
The paper’s framing insight is that this is really two coupled problems. First, describing the valid region requires machine-generated precision — the constraints number in the hundreds per operator, vary with tensor shapes, and connect architectural limits to tunable parameters only through chains of intermediate quantities (a scratchpad bound constrains a product of loop lengths, which constrains tile factors). Second, searching the resulting region requires constraint-aware machinery, because the region is not a box: it is a jagged archipelago where a mutation that nudges one tile size strands you outside validity. Heron’s two halves — constraint generation and constraint-preserving evolution — answer the two halves exactly, and the payoff lands not just against other compilers but against the vendors’ own hand-tuned crown jewels.
What people did before, and where it broke
- Vendor libraries (cuDNN, cuBLAS, oneDNN, PopLIBS). Peak-tuned by teams over months-to-years; inflexible against new operators and shapes, and — the evaluation shows — beatable: Heron averages 2.00× over them, because hand-tuning cannot exhaustively cover every shape.
- Manual-template compilers (AutoTVM, UNIT). Experts write templates per operator per backend; the template bakes in a few simple constraints, excluding much of the valid space (and often the optimum) — visualized in the paper as a tidy box missing the best programs.
- Auto-template compilers (Ansor, FlexTensor, AMOS). Rules generate bigger spaces without manual templates — but the rules were designed for general-purpose targets, blind to DLA constraints: spaces balloon with invalid programs, and search wastes its budget discovering invalidity by compilation failure.
- Polyhedral compilers (AKG). Wider legal transformations via dependence analysis, TensorCore support included — but still not constraint-complete for DLA resource limits, and outperformed by 1.52–2.85× here.
- Constraint-handling GAs from the optimization literature. Penalty functions and multi-objective tricks do not guarantee valid offspring; repair and SAT-decoder methods guarantee validity but scramble inherited structure (the decoder maps mangled genotypes to legal phenotypes, losing the parents’ good genes). Heron’s evaluation shows all four trailing CGA, worse as problems grow.
How Heron works
Constraints born with the schedule, preserved through evolution
-
Schedule template generation (rules S1–S3 + classics) new
Static analysis walks the operator's computation DAG in reverse topological order, applying rules: TENSORIZE (S1) pattern-matches computations onto hardware intrinsics (GEMM maps [i,j,r]→[m,n,k] on TensorCore's wmma; convolutions via im2col); ADD MULTI-LEVEL SPM (S2) and MULTI-SCOPE SPM (S3) insert cache_read/cache_write stages matching the accelerator's scratchpad hierarchy (shared memory + wmma fragments); multi-level tiling and the general-purpose rules complete the template. Output: a transformed program skeleton with tunable parameters.
-
Constraint generation (rules C1–C6, six constraint types) new
A second rule pass scans every generated schedule primitive: loop splits/fusions emit PROD constraints tying sub-loop products to parent lengths (C1/C2); enumerated choices emit IN constraints (C3); stage fusion emits SELECT constraints tying loop lengths to placement (C4); scratchpad usage emits PROD+SUM+LE chains bounding total footprint by capacity (C5); DLA-specific quirks (TensorCore's m·n·k=4096, VTA's loop ordering) emit dedicated constraints (C6). For one GEMM: 173 variables, 372 constraints — written by no human.
-
The space IS a CSP new
Variables (tunable parameters + auxiliaries) plus all generated constraints form CSP_initial — a formal object a constraint solver can sample. Random valid programs come from RandSAT: the solver returns assignments satisfying everything, so even the initial population wastes zero measurements on invalid candidates.
-
CGA: crossover and mutation on problems, not programs new
Each round, an XGBoost cost model ranks features by importance; the top-k become KEY VARIABLES. Crossover picks two parent solutions and, for each key variable v, adds constraint IN(v, [parent1's value, parent2's value]) — a NEW CSP whose solutions inherit parental structure. Mutation randomly deletes one added constraint, reopening room the crossover closed. The solver then samples offspring from each new CSP: since new constraints only ADD to CSP_initial, every offspring satisfies the original constraints by construction.
-
Measure, learn, iterate new
Offspring are scored by the cost model; an epsilon-greedy selection sends the most promising (plus exploratory picks) to real hardware. Measurements retrain the model; survivors seed the next round. Compilation-time budget stays comparable: hardware measurement dominates (76% of time), the solver-based CGA costs 23%, model training under 1% — and better search means FEWER wasted measurements (87%/82% of AutoTVM/AMOS total time).
-
Porting to a new accelerator
Adapting Heron means adjusting the rule set, not rewriting a compiler: point S1 at the new intrinsics, S2/S3 at the new memory hierarchy, C5 at the new capacities, C6 at the new quirks. The constraint machinery and CGA are target-independent.
The idea
Constraints are not obstacles to the search — they are the map. Prior compilers treated DLA validity as something to discover the hard way, one failed compilation at a time; Heron treats it as derivable knowledge. The derivation is the elegant part: every constraint is born from a schedule primitive — the split that created two sub-loops also creates PROD(parent, [sub1, sub2]); the cache stage that touched shared memory also creates the capacity inequality; the tensorize that claimed the matrix unit also creates the shape menu. Because schedule and constraints emerge from the same static analysis, they cannot drift apart, and the hundreds-per-operator scale that defeated hand-writing becomes free. The reification rhymes with moves this site has seen — a safety poset, a Steiner grid — but here the formal object is a CSP, chosen precisely because industrial-strength solvers exist to sample it.
Evolve the problems, not the solutions. The deep fix to genetic search is a change of representation. Classic crossover splices two concrete parameter vectors — and in a jagged valid region, the splice almost always lands outside (hence GA’s degeneration to random restarts). CGA never touches concrete vectors: crossover narrows the CSP by pinning key variables to parental values, mutation re-widens it by dropping one pin, and the solver — which understands every constraint — produces the offspring. Validity is not checked, repaired, or penalized; it is inherited, because adding constraints to a satisfiable problem can only shrink the solution set within the valid region. Meanwhile the cost-model-driven choice of key variables makes the pins meaningful: pinning what predicts performance is how parental “good genes” survive — exactly what SAT-decoder approaches lose (their evaluation shows it: GA-2 fades as problems grow).
Better spaces are harder spaces — plan for both. The paper’s search-space visualization makes an easily-missed point: pruning invalid programs does not smooth the landscape, it sharpens it — neighboring valid programs differ wildly in performance, because the buffer zones of mediocre-but-valid candidates are gone. A high-quality space without constraint-aware search is nearly useless (SA and GA both flounder in it); constraint-aware search without the high-quality space has nothing to find. The two contributions are a matched pair, and the ablations price each: CGA beats SA/GA/random in half the exploration steps, and beats all four classic constraint-handling GA techniques, with the gap widening on larger problems.
A GEMM’s journey to TensorCore
From tensor expression to a program faster than cuBLAS
wmma = TensorCore's matrix-multiply intrinsic (shape-constrained). CSP = constraint satisfaction problem. Key variables = top cost-model features. Numbers from the paper's evaluation.
Step 1 of 6
Rules build the schedule skeleton
The GEMM C[i,j] += A[i,r]·B[r,j] arrives as a tensor expression. Walking its DAG, rule S3 inserts a write-cache stage (C.wmma accumulator), S2 inserts shared-memory read-caches for A and B, S1 tensorizes the innermost loops onto the wmma intrinsic by mapping [i,j,r]→[m,n,k], and multi-level tiling splits every loop. The result: a five-stage pipeline (global→shared→registers→TensorCore→shared→global) bristling with tunable tile factors.
the same rules, re-pointed, target DL Boost or VTA — porting is rule editing convolutions tensorize via im2col before the mapping
Why it works
- Every constraint originates in a schedule primitive → generating them together by static analysis makes hundreds-per-operator scale free, shape-adaptive, and drift-proof → the search space contains all valid programs and only valid programs.
- The space is a formal CSP → industrial constraint solvers can sample it uniformly (RandSAT) → initial populations and all offspring are valid, so the entire measurement budget goes to real programs.
- Adding constraints to a satisfiable CSP only shrinks its solution set → crossover-by-pinning and mutation-by-unpinning keep every offspring inside the original valid region → the validity guarantee costs nothing and needs no repair machinery.
- Key variables come from cost-model feature importance → the pins preserve exactly the choices that predict performance → parental good genes survive evolution, which SAT-decoder and penalty methods structurally lose.
- Pruning mediocre-invalid buffer zones concentrates performance but sharpens the landscape → constraint-preserving search is the necessary complement to the constrained space → the two halves of Heron are a matched pair, each ablated separately.
What it costs
- Rules are still human artifacts. The schedule rules (S1–S3) and constraint rules (C1–C6) encode expert abstractions of DLA families; a genuinely novel accelerator paradigm (or an intrinsic the pattern-matcher cannot recognize) needs new rules — automation moved up a level, not away.
- Per-shape search remains. Heron searches per operator and shape configuration (~90 minutes per operator at 2,000 trials) — a library-building workflow, not a JIT; dynamic shapes inherit the classic tensor-compiler weakness.
- Solver in the loop. CGA spends 23% of compile time in constraint solving; the approach leans on modern CSP solver efficiency, and pathological constraint systems could bite.
- Cost model dependence. Key-variable extraction and candidate ranking both trust XGBoost feature importances; the CGA-1 ablation shows random key variables erode gains, and model accuracy decays on the largest problems.
- Hardware-measurement dominance. 76% of compile time is timing programs on the device — Heron reduces wasted measurements but cannot escape needing the accelerator in hand, unlike forecast-only approaches.
The evaluation
Three commercial-grade accelerators with different constraint regimes (TensorCore’s shape menus, DL Boost’s fixed VNNI shapes, VTA’s buffer/order limits), operator- and network-level benchmarks, four auto-compiler baselines plus vendor libraries, search-space visualizations, algorithm ablations against classic constraint handling, and compile-time accounting.
Three routes to accelerator libraries
| Property | Vendor hand-tuned (cuDNN / oneDNN) | Exploration compilers built for CPUs/GPUs (AutoTVM / Ansor / AMOS / AKG) | Heron (auto-constraints + CGA) |
|---|---|---|---|
| Where validity knowledge lives | |||
| Search behavior in DLA spaces | No search — fixed implementations | ||
| Performance (averages) | AutoTVM reaches 46% of cuDNN on VGG-16 TensorCore convolutions | ||
| Compilation cost | Months of engineering, amortized | ~90–147 minutes per operator (2,000 trials) | |
| Portability to a new accelerator | A new library project | Rule/template rewrites of uncertain scope; DLA constraints unexpressed |
Check yourself
Check your understanding
1. Given a PERFECTLY constrained search space for TensorCore, classic simulated annealing and genetic algorithms still fail to beat random search. Predict the two distinct failure mechanisms.
2. CGA's crossover adds constraints IN(v, [parent1_v, parent2_v]) for each key variable, and its mutation deletes one such constraint. Why does this guarantee valid offspring where penalty, repair, and SAT-decoder GAs cannot deliver both validity and inheritance?
3. Why must the constraints be generated automatically rather than written by the compiler engineers who, after all, designed the schedule rules?
4. Heron beats vendor hand-tuned libraries — cuDNN by 2.69× average on TensorCore, Intel's oneDNN by 1.49× on Intel's own accelerator. What makes this plausible rather than suspicious, and what nuance applies?
Sources
- ACM DL: Heron: Automatically Constrained High-Performance Library Generation for Deep Learning Accelerators — ASPLOS 2023 (open access)