48 long-form articles on compiler numerics, layouts, scheduling, and delivery. The stories often start with a small question: why does computing a mean require moving data? Why can a program not find a file that exists? Why does a view keep memory alive? Why does Debug work while Release fails?
This is the complete English counterpart of the Chinese collection. Each article retains its original ID and filename so the two editions can be matched directly. The English edition is self-contained.
Where to start
- For a complete debugging story: Debug Works, but Release “Optimizes Away” a Write.
- For quantization problems: The Multiplication Is Right; the Scale Is Wrong: An Integer Kernel’s Two Ledgers → Once BatchNorm Becomes Multiply-Add, the Numerical Work Begins → Epsilon Was Nonzero—Until It Nearly Vanished in the Integer Domain.
- For shapes and layouts: Why Does Reshape Need Code? The Elements Stay the Same; Their Route Changes → Broadcasting: Sometimes the Right Address Is the One That Does Not Move → The First Row Works, the Second Disappears: Alignment, Strides, and Padded Constants.
- For asynchronous execution and resource ownership: Why Does Someone Keep Borrowing My “Temporary” Register? → The View Moved No Data. Why Can’t We Return the Memory? → I Waited for the Event. Why Isn’t the Data Ready?.
- For compiler delivery: “I Only Rebuilt It.” Why Did the Installation Directory Disappear? → The Library Is in the Package. Why Can’t the Program Find It? → The Compiler Moved. Its Lookup-Table Module Didn’t Get the Address → Why Does the Same Release Package Get a Different Hash Every Time?.
- For backend architecture and verification: An Instruction’s Four Identities: Why Code Generation Needs More Than Strings → The Assembly Looks Right. Does That Mean the Machine Code Is Right? → The Most Useful Words in an Operator Specification May Be “Not Yet Confirmed”.
Numerical Correctness — Integers and the Scales That Interpret Them
| Article | Starting question |
|---|---|
| Just Take the Mean—Why Is the Compiler Writing Loops? | Lower arbitrary reduction axes into executable loops and account for layout and transfer costs. |
| The Vanishing Dimension: How keep_dims=false Can Break an Inverse Permutation | Preserve axis identity when dimensions disappear, then reconstruct the inverse permutation. |
| Max, Min, and Sum: Similar Operators, Different Mathematical Homework | Share reduction structure without copying initialization, accumulation, or rescaling semantics. |
| This Reduction Does Nothing—Why Can’t We Delete It? | A mathematical identity can still require a change of quantized representation. |
| The Multiplication Is Right; the Scale Is Wrong: An Integer Kernel’s Two Ledgers | Track input scales, output scales, and the range of the intermediate product. |
| Once BatchNorm Becomes Multiply-Add, the Numerical Work Begins | Follow fixed statistics through channelwise affine transforms, multipliers, shifts, and biases. |
| Just a Few Channel Parameters—So Why Is Local Memory Full? | Avoid materializing channel parameters across a whole tensor while preserving broadcasting. |
| Build a Dedicated Operator, Then Remove It: A Design Change Worth Recording | Compare the expressiveness and maintenance cost of a dedicated affine operator and its decomposition. |
| Epsilon Was Nonzero—Until It Nearly Vanished in the Integer Domain | Follow epsilon, squares, and reciprocal square roots through normalization range planning. |
| Floating Point Passes, Quantization Fails: A Rewrite Gives the Output the Input’s Identity | Treat the rewritten result type as both a container and a numerical contract. |
| The Importer Got Clever Too Soon: Algebraic Optimization before Quantization Metadata | Understand the interaction between algebraic rewrite order, metadata matching, and constants. |
Operators and Layouts — Putting Mathematics into Memory
| Article | Starting question |
|---|---|
| Grouped Convolution: Once You Slice the Cake, Slice the Labels Too | Split input and weight groups while carrying their quantization metadata with them. |
| Transposed Convolution Weights: The Shape Is Honest, but Memory Speaks Another Dialect | Derive slices from actual weight storage, not just a logical dimension order. |
| Why Does Reshape Need Code? The Elements Stay the Same; Their Route Changes | Prove the linear element mapping and distinguish shape changes from physical rearrangement. |
| When the Debugger Starts Lying: One Permute, Three Ways to Fix Dump | Three alternative branch fixes show why observation paths need layout contracts too. |
| Broadcasting: Sometimes the Right Address Is the One That Does Not Move | Build per-axis address plans for scalars, lower-rank inputs, and more complex broadcasts. |
| The First Row Works, the Second Disappears: Alignment, Strides, and Padded Constants | Make logical widths, physical strides, padded storage, and parameter layouts agree. |
| Subtracting Zero Can Disappear; Subtracting from Zero Cannot | Keep constant folding, commutativity, and operand direction as separate decisions. |
| Abs and Sign: One Line of Arithmetic Does Not Make Their Parameter Contracts Interchangeable | Carry a unary operator’s definition through types, quantization, and parameter encoding. |
| Who Moved My Scratch Register? Teaching an Emitter to Borrow and Return | Replace informal scratch-register conventions with explicit borrowing and lifetime rules. |
| Putting Activation Inside Convolution: Preserve the Quantization Boundary Before Removing the Node | Preserve intermediate quantization and legality when fusing convolution with activation. |
| A Sigmoid After MatMul: Why the Compiler Still Refuses to Fuse It | Understand how consumers, views, and dependencies constrain matrix-activation fusion. |
| When Weights Move to the Left: A Transpose Identity That Moves the Whole Compiler Chain | A transpose identity starts the rewrite; weight identity and quantization axes must follow. |
Resources and Scheduling — Who Still Needs This Data?
| Article | Starting question |
|---|---|
| Why Does Someone Keep Borrowing My “Temporary” Register? | Express register ownership through scope and define the limits of automatic release. |
| A Few More Branches in the Graph—and Synchronization Registers Run Out First? | Explain how graph fan-out and dependency joins create synchronization-resource pressure. |
| The View Moved No Data. Why Can’t We Return the Memory? | Follow asynchronous consumers through view chains before reclaiming underlying storage. |
| The Address Fits. Why Does the Compiler Say Memory Is Full? | Separate encodable addresses, allocation intervals, and actual memory budgets. |
| Why Write the Same Final State Twice? | Distinguish persistent state, final state, and direct-output buffers. |
| I Waited for the Event. Why Isn’t the Data Ready? | Make synchronization events cover the actual production of data across execution engines. |
| You Caught the Exception. What Happens to the Half-Written Machine Code? | After catching an error, account for the state and output already produced. |
| One More Loop, and the Binary Snapshot Looks Like a Different Program | Examine how loops, labels, and independent emitter instances affect binary determinism. |
| “I Parsed a Number” Does Not Mean the Input Is Valid | Check full input consumption, signs, and field ranges after parsing succeeds. |
| Fewer Operations—So Why Disable the Optimization? | Treat disabling an optimization as a design decision about slicing and quantization contracts. |
Compiler Engineering — From a Development Tree to a Deliverable
| Article | Starting question |
|---|---|
| Debug Works, but Release “Optimizes Away” a Write | A required write hidden in an assertion disappears when checks are disabled. |
| “I Only Rebuilt It.” Why Did the Installation Directory Disappear? | Define the responsibilities and failure states of environment setup, builds, and installation. |
| One Version of the Headers, Another Version of the Generator | Headers, libraries, generators, and caches jointly determine toolchain identity. |
| The Library Is in the Package. Why Can’t the Program Find It? | Connect real library files, SONAMEs, linker names, and runtime search paths. |
| The Compiler Moved. Its Lookup-Table Module Didn’t Get the Address | Use real functionality and missing-resource tests to validate relocation. |
| Why Is Packing Compiler Outputs into One File Hard? | Treat a model file as a protocol with offsets, lengths, and ownership. |
| Compilation Failed. Why Is There Still a “Successful Model” in the Directory? | Make output directories, temporary artifacts, and stale files part of a clear success contract. |
| Why Does the Same Release Package Get a Different Hash Every Time? | Separate archive-event time, package timestamps, and byte reproducibility. |
| The Assembly Looks Right. Does That Mean the Machine Code Is Right? | Understand what pseudoassembly, assembly, machine code, and mathematical references each prove. |
| The Most Useful Words in an Operator Specification May Be “Not Yet Confirmed” | Keep unknowns explicit rather than turning example tables into capability promises. |
| You Found the Operator’s Name. Does That Make It Supported? | Require evidence for a complete compilation path before calling an operator supported. |
| An Instruction’s Four Identities: Why Code Generation Needs More Than Strings | Assign responsibilities and diagnostics across operation, kernel, emission, and encoding layers. |
| It Only Moves Data. How Can It Still Be Wrong? | Preserve coordinates, strides, aliasing, and quantization when moving data. |
| Same Output Shape, Different Answers: Pooling, Resizing, and Index Reductions | Let window denominators, sampling coordinates, and index rules determine actual results. |
| A Function Name Cannot Hold Its Numerical Contract | Specify domains, approximations, precision, and axes beyond a function’s name. |
Follow a question across the series
- Can this rewrite be removed? Identity and Requantization → Rewrite Result Types → Optimization Preconditions: mathematical identity, result representation, and optimization preconditions must all hold.
- Is the observed error the real error? Debug Output Layout → Layered Regression Tests: debugging layouts and test baselines can be wrong too.
- Do fewer nodes always mean faster execution? Broadcast Memory → Convolution Fusion → MatMul Fusion Boundaries: movement, memory, rounding boundaries, and consumers determine the potential benefit.
- What does an operator name promise? Operator Support → Pooling and Sampling → Nonlinear Functions and Normalization: a name and an output shape leave much of the numerical contract unspecified.
- Does a file’s existence mean success? Assertion Side Effects → Model File Protocols → CLI Output Contracts → Error Boundaries: required side effects and output states need verifiable completion conditions.
Each article is an independent Markdown file, ready to read, edit, or import into a blog platform. Tables and code blocks require no online resources.
Connections to earlier blog posts
- Build foundations: Building and Managing Multiple Files → Build Stages, Toolchain Consistency.
- Loading foundations: Compilation, Loading, and Execution → Dynamic Library Resolution, Compiler Relocation.
- Memory foundations: Memory Management and Task Switching → View Liveness, Addresses and Capacity.
- Debugging foundations: Engineering Debugging Experience → Debug Output Layout, Assertion Side Effects, Layered Regression Tests.
Editorial calendar
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. All the images used in the blog are my original works or AI works, if you want to take it,don't hesitate. Thank you !