Right In-Place (RiP) Convolution: A Simple, General, and Near-Optimal Strategy for Memory-Efficient CNN Inference
Organizations: PowerLabs Technologies, Lagos, Nigeria
Abstract
Activation memory, not compute, limits CNN inference on constrained hardware such as microcontrollers. Direct in-place convolution removes the dual-buffer cost, but the memory-optimal formulation of Gural and Murmann assumes valid padding, unit stride, unit dilation, and odd square kernels, and needs a non-sequential traversal costing inference time in transposes. We identify two regimes in which their published closed form does not hold: (1) an under-allocation of exactly scalars, active on every convolutional layer of their own deployed network and manifesting as a silent corruption of still-live input; (2) an unbounded overestimate, up to , once the critical leg leaves the output grid. We correct both and generalize to arbitrary stride, dilation, padding, and rectangular kernels. We then propose Right In-Place (RiP) convolution, a bit-identical operation in which every layer reads its input right-aligned in a shared workspace and writes its output left-aligned from index zero. The debt is piecewise affine in the output pixel index, so evaluating its breakpoints in yields the minimum safe gap without enumerating the output grid, with row-major access preserved. Across random layers RiP produced no corruption, and across 84 convolutional layers from 25 architectures it matches the herringbone workspace exactly on 58 and within 5% on 81, using 24.8% less memory than dual buffering on average. Written into TinyEngine's kernels and deployed to a Raspberry Pi Pico 1 and Pico 2, it cuts peak activation memory across eleven MCUNet models by 12.5 to 33.3% at unchanged cycle counts and bit-identical outputs, raising the number of models that fit the Pico 1's 256 KB SRAM from six to nine.
Figures & tables
| Method | Axis | General | Sequential | Bound | Restrictions |
|---|---|---|---|---|---|
| Herringbone [ 9 ] | spatial in-place | ✓ | ✓ | valid, , , odd square | |
| Replace [ 9 ] | spatial in-place | ✓ | ✓ | valid, , , odd square | |
| In-place DW [ 20 ] | channel in-place | ✓ | – | depthwise only | |
| MCUNetV2 [ 19 ] | cross-layer patch | ✓ | – | – | recomputation overhead |
| RAMAN [ 18 ] | hardware overlay | ✓ | – | requires custom accelerator | |
| CMSIS-NN Replace [ 25 ] | inter-layer arena | ✓ | ✓ | whole-tensor granularity |
| G&M | Truth | Err. | |||||
| Limitation 1: G&M’s deployed MNIST network, conv_0–conv_2 | |||||||
| 1 | 5 | 3 | 14 | 0.5 | 531 | 533 | |
| 5 | 8 | 3 | 12 | 3.3 | 148 | 149 | |
| 8 | 11 | 3 | 10 | 5.3 | 45 | 46 | |
| Limitation 2: critical leg exceeds the output grid | |||||||
| 3 | 4 | 5 | 8 | 12 | 79 | 7 | |
| Peak activation memory (B) | Pico 2 cycles (M) | Pico 1 time (ms) | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Model | Buffer (B) | Base | RiP | Ratio | Base | RiP | Ratio | Base | RiP | Ratio | Acc. | Bit-exact |
| MCUNet-in0 | 3,984 | 46,080 | 36,864 | 39.5 | 39.7 | 1,772.4 | 1,772.0 | ✓ | ||||
| MCUNet-in1 | 5,864 | 92,160 | 73,728 | 70.0 | 70.3 | 3,601.1 | 3,607.8 | ✓ | ||||
| MCUNet-in2 | 14,976 | 204,800 | 179,200 | 307.0 | 307.2 | 15,978.1 | 15,999.5 | ✓ | ||||
| MCUNet-in3 | 18,536 | 247,808 | 185,856 | 380.5 | 380.8 | – | 19,388.2 | – | ✓ | |||
| MCUNet-in4 | 16,520 | 409,600 | 307,200 | 708.2 | 708.7 | – | – | – | ✓ | |||
Appendix figures & tables5 assets
Supplementary material from the paper’s appendix.
Appendix
| Convolution setup ( Sec. 4.1 ) | |
|---|---|
| Input, output activation tensors | |
| Input height, width, channel count | |
| Output height, width, channel count | |
| Padded input height, width | |
| Output tensor size, | |
| Kernel height, width | |
| Tier | Generator | Share |
|---|---|---|
| 1 | plain convolution, | |
| 1 | same padding, | |
| 1 | strided downsampling | |
| 1 | inverted-bottleneck expansion | |
| 1 | projection, | |
| 2 | collapsed minor axis, |
| Family | Gen. | Exact | Max | Save | Dense | Timed | Cost | ||
|---|---|---|---|---|---|---|---|---|---|
| ResNet-50 | 11 | 4 | 10 | 11 | 6 | ||||
| ResNet-56 (pruned) | 5 | 5 | 4 | 5 | 5 | ||||
| VGG-16 | 4 | 4 | 0 | 4 | – | – | |||
| VGG-16 (pruned) | 3 | 3 | 0 | 1 | 3 | ||||
| MobileNetV1 | 6 | 1 | 5 | 6 | 3 | ||||
| MobileNetV2 | 5 | 1 | 4 | 5 | 2 |
| MILP size | Compile (s) | Peak activation (KB) | Tensor placement | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Model | Ops | Res. | Vars | Constr. | Dual buf. | RiP | Ratio | Dual buf. | RiP | Ratio | In-place (%) | Shift (#) |
| MobileNet | 29 | 0 | 1,361 | 1,969 | 0.08 | 0.14 | 1.69 | 1,176.0 | 784.0 | 2/3 | 60.0 | – |
| MobileNetV2 | 64 | 10 | 6,364 | 8,813 | 0.26 | 0.52 | 2.01 | 1,470.0 | 1,176.0 | 4/5 | 49.2 | – |
| MobileNetV3-S | 109 | 15 | 18,201 | 24,834 | 1.08 | 1.49 | 1.37 | 392.0 | 220.5 | 9/16 | 64.5 | – |
| MobileNetV3-L | 122 | 18 | 22,751 | 30,967 | 1.27 | 1.42 | 1.12 | 980.0 | 784.0 | 4/5 | 82.1 | – |
| VGG-16 | 21 | 0 | 729 | 1,077 | 0.11 | 0.16 | 1.49 | 6,272.0 | 3,150.1 | 0.502 | 54.5 | 1 |