Majid Al-RaimiFine-grained, N:M and channel pruning in practice

COE 592Lecture 4.1Part 04

Fine-grained, N:M and channel pruning in practice

Trade-offs of each granularity with real numbers: fine-grained compression ratios, NVIDIA 2:4 pattern sparsity with its compressed format and accuracy table, and channel pruning with non-uniform per-layer sparsity versus uniform shrinking.

Concepts
5
Slides
19-25
Reading
30 min
Understood
0/5 concepts

Why this part matters

Your research targets embedded deployment, where the question is never "how many weights can I remove" but "which removal makes this board faster". This part is where the granularity spectrum of part 03 meets real hardware.

It explains why a 9x compressed AlexNet (or a 13x compressed VGG-16) can run no faster on a GPU, why NVIDIA built a 2:4 pattern into its Ampere Tensor Cores, and why the model-compression papers you will cite (AMC, channel pruning) search for per-layer ratios instead of one global number. These are also the three most examinable facts in the lecture: which granularity gives speedup on commodity GPUs and why, what sparsity 2:4 means, and why non-uniform per-layer sparsity beats uniform shrink.

By the end you can

  1. Explain why fine-grained pruning gives the largest compression ratio but little or no speedup on GPUs with standard kernels, and name the hardware that can exploit it.
  2. Define N:M sparsity under the NVIDIA convention, compute its sparsity for any N and M, and explain why the slide's wording is ambiguous.
  3. Derive the 2:4 compressed layout and compute its memory saving for FP16 and INT8 values.
  4. State the pro and con of channel pruning and show how pruning one layer's channels shrinks two layers.
  5. Argue with AMC's measured Pixel 1 numbers why per-layer sparsity ratios beat uniform shrink at equal latency.

Go back to the very first picture of this lecture: a network before and after pruning, with individual synapses cut out while every neuron stays. That picture is fine-grained pruning, the synapse pruning of slide 4 seen through the lens of granularity. Slides 19 and 20 bring it back only to attach numbers to it, so treat them as a short callback rather than new material.

The numbers are the ones from part 02. Han et al. pruned AlexNet from 61 M to 6.7 M parameters and VGG-16 from 138 M to 10.3 M without losing accuracy, a pruning ratio of roughly 89% and 93% (Han, Pool, Tran and Dally, NIPS 2015). Those results are only possible because the method may zero any single weight, wherever it sits in the tensor. The slide calls this "flexible pruning indices": the set of surviving positions is unconstrained, so the algorithm can find redundant weights anywhere and usually reaches the largest compression ratio of all granularities.

NetworkParameters beforeParameters afterReduction
AlexNet61 M6.7 M9x
VGG-16138 M10.3 M12x (paper: 13x)
GoogleNet7 M2.0 M3.5x
ResNet-5026 M7.47 M3.4x
Fine-grained pruning results as printed on slide 20, reused from slide 11 (source: Han, PhD thesis, Table 3.1)

Why flexibility is expensive at run time

Now look at what the flexibility leaves behind. After fine-grained pruning the weight tensor still has its original shape; it is simply riddled with zeros at irregular positions. A dense matrix multiply on a GPU does not know the zeros are there and multiplies them anyway, so the work is unchanged. To skip them you must store the weights in a sparse format such as CSR, CSC or COO, where every surviving value carries an index saying where it belongs. Mishra et al. note that these formats make memory accesses data dependent and that the index metadata can cost up to 200% of the weight storage when the weights are 8-bit (Mishra et al., 2021). Zhou et al. summarize the situation in one line: fine-grained sparsity "can achieve a high compression ratio but is not hardware friendly and hence receives limited speed gains" (Zhou et al., ICLR 2021).

Zeros land anywhere in the tile, and every survivor needs an address written next to it. Flexibility buys compression and charges an index per weight.

That is why the red line on slide 20 matters more than the table. Speedup from fine-grained sparsity needs hardware built around indices. Han's own EIE accelerator is the example the MIT source deck names: by reading compressed weights and skipping zero activations, it ran fully-connected layers 189x faster than a CPU and 13x faster than a GPU running the uncompressed network (Han et al., ISCA 2016). With sparse kernels the picture depends on batch size: in EIE's own measurements cuSPARSE ran pruned FC layers 4x to 9x faster than dense at batch 1 on a Titan X, but slower at batch 64, which is why the slide says "not GPU (easily)". On an ordinary GPU with dense kernels, the same pruned network runs at roughly dense speed.

EIE on compressed fully-connected layers (Han et al., ISCA 2016)

Speedup over CPU
189x
Speedup over GPU
13x
Energy efficiency over GPU
3400x

Recall

Why does fine-grained pruning usually reach a larger compression ratio than channel pruning, and why does that not translate into GPU speedup?

It may zero any weight, so it finds redundancy anywhere. But survivors sit at irregular positions, need per-weight indices and data-dependent memory access, and dense GPU kernels cannot skip them. Custom hardware such as EIE can (13x over a GPU running the dense model).

Quick check

A layer is pruned to 90 percent unstructured sparsity and run on a plain GPU with dense kernels. What happens to latency?

Take one row of eight FP16 weights and split it into two groups of four. In each group keep the two largest magnitudes and zero the other two. Every group now has exactly two zeros and two nonzeros, so the row is 50% sparse, and so is every other row treated the same way. That is 2:4 sparsity, the classic case of N:M sparsity and the reason the lecture lists pattern-based pruning as its own step on the granularity spectrum.

The general rule needs one careful sentence, because the slide's sentence is ambiguous. In NVIDIA's definition, which is the one hardware implements, an N:M pattern allows at most N nonzero values in every contiguous group of M. The Ampere whitepaper describes 2:4 as a matrix "that allows two non-zero values in every four-entry vector", and Mishra et al. write of "the 2 nonzero values in each group of 4" (NVIDIA, 2020; Mishra et al., 2021). Slide 21 instead says that "N of them is pruned". For 2:4 the two readings agree, since two kept and two pruned are the same thing. For any other pattern they do not.

s=1NMs = 1 - \frac{N}{M}
Sparsity of an N:M pattern under the N-nonzero convention

Why a pattern is the middle of the spectrum

Inside each group of four the pattern is still fine-grained: any two of the four positions may survive, six possible masks, chosen by magnitude. Across the matrix it is rigidly structured: every group holds exactly two values, no more and no fewer. Mishra et al. point out what this buys: because the sparsity is constant across the matrix, "there is no indirection required; a nonzero value's position in memory can be determined from the compression rate directly" (Mishra et al., 2021). The hardware always knows that group g starts at value slot 2g. That is the difference between a lookup and an address calculation, and it is what makes fine-grained-in-the-small, structured-in-the-large worth a place of its own.

The compressed format

The rule also fixes the storage layout, which is the right-hand panel of slide 21. An R by C dense matrix becomes an R by C/2 block of nonzero values plus an R by C/2 block of 2-bit indices, where each index records the position, 0 to 3, of a kept value inside its group of four. Two bits are enough because a group has only four positions. One corner case keeps the format regular: if a group happens to have three or four zeros after training, two values are stored anyway, padded with zeros as needed (Mishra et al., 2021).

Each run of four snaps to two survivors, the survivors slide left into a half-width block, and a 2-bit sidecar records where each came from.

Worked example

Compressing an 8 by 8 FP16 matrix

  1. Dense storage

    64 values at 16 bits each: 64 x 16 = 1024 bits.
  2. Kept values

    Half survive, 32 values: 32 x 16 = 512 bits.
  3. Indices

    One 2-bit position per kept value: 32 x 2 = 64 bits.
  4. Compressed total

    512 + 64 = 576 bits.
  5. Result

    1024 / 576 = 1.78x smaller, 43.75% saved. Per group of four the arithmetic is 64 bits versus 36 bits, which is exact for a matrix of any size.

2:4 storage for FP16 weights, 8 by 8 matrix

Dense FP16
1024 bits
Kept values
512 bits
2-bit indices
64 bits
Compressed total
576 bits
Ratio
1.78x
Index overhead on the kept values
12.5%

The same matrix with INT8 weights

Dense INT8
512 bits
Kept values
256 bits
2-bit indices
64 bits
Compressed total
320 bits
Ratio
1.6x
Index overhead on the kept values
25%

The two tables carry an insight that matters when you combine pruning with the quantization lectures: the index costs two bits whatever the value width, so the narrower the value type the more the index costs relatively. Mishra et al. give the same figures, about 44% saved for 16-bit and about 38% for 8-bit weights, which is why NVIDIA says the format cuts storage and bandwidth by "almost" 2x rather than exactly 2x (Mishra et al., 2021; NVIDIA, 2020).

Where the 2x speedup comes from

Storage is only half of the payoff. The Ampere A100 added Sparse Tensor Core instructions that take a 2:4 compressed operand and, in the whitepaper's words, "skip the compute on entries that have zero values, resulting in a doubling of the Tensor Core compute throughput": a 16 x 8 x 16 matrix multiply instruction completes in half the cycles of its dense counterpart (NVIDIA, 2020). Software reaches it through TensorRT 8 and cuSPARSELt; the slide's link covers the TensorRT 8.0 path. Zhou et al. restate the same about 2x for the A100, citing NVIDIA rather than measuring it themselves (Zhou et al., ICLR 2021).

Try the pattern yourself below. Switch the convention from "N nonzero" to "N pruned" at 2:4 and nothing changes; switch it at 1:4 and the sparsity flips from 75% to 25%, which is exactly the ambiguity flagged above. Then toggle FP16 to INT8 and watch the index overhead double.

SimulatorN:M pruner: keep the largest magnitudes in every group
-0.380.180.130.72
0.08-0.37-0.790.78
-0.13-0.220.30-0.58
0.590.260.610.06
kept values (2 per group)
-0.380.72
-0.790.78
0.30-0.58
0.590.61
position indices
0011
1011
1011
0010
Sparsity50.0%8 of 16 zero1 - 2/4
Index width2bitslog2(4) per kept value
Per group36of 64 bits32 value + 4 index
Compression1.78x43.8% savedindex overhead 12.5%
Scaled to an 8 × 8 matrix (16 groups): dense 1024 bits, compressed 576 bits, ratio 1.78x. The ratio never depends on matrix size, only on M, N and the value width.

Recall

Define 2:4 sparsity, give its sparsity percentage, and state the storage layout.

Two nonzeros in every contiguous four (two zeros), so 50%. Stored as half the values plus a 2-bit index per kept value: 36 bits per group of four FP16 weights instead of 64, about 1.78x.

Recall

Under the NVIDIA convention, what is the sparsity of 1:4 and of 4:8?

1:4 keeps one of four, so 75% sparsity. 4:8 keeps four of eight, so 50%.

Quick check

A weight matrix satisfies the 2:4 pattern. What fraction of its weights is zero?

Quick check

Using NVIDIA's convention, how many weights in every group of four are zero under a 1:4 pattern?

A format that halves storage and doubles matmul throughput is worth nothing if the network gets worse. So look at one row first: ResNet-50 on ImageNet scores 76.1% top-1 dense in FP16 and 76.2% after 2:4 pruning. Half the weights are gone and the accuracy is unchanged; the extra 0.1 is run-to-run noise, not a gain.

The rule that produced that row is NVIDIA's three-step recipe. Train the dense network as usual. Prune it to 2:4 by keeping the two largest magnitudes in every group of four, which fixes the mask. Then retrain with the mask held fixed, using the original schedule and hyperparameters, so the survivors absorb the job of the pruned weights. That last step is the fine-tuning loop of part 02 applied under a structural constraint, and the whitepaper reports "virtually no loss in inferencing accuracy" across dozens of networks with it (NVIDIA, 2020). The choice of mask by magnitude inside each group previews the magnitude criterion of part 05.

NetworkData setMetricDense FP16Sparse FP16Change
ResNet-50ImageNetTop-176.176.2+0.1
ResNeXt-101_32x8dImageNetTop-179.379.30.0
XceptionImageNetTop-179.279.20.0
SSD-RN50COCO 2017bbAP24.824.80.0
MaskRCNN-RN50COCO 2017bbAP37.937.90.0
FairSeq TransformerEN-DE WMT'14BLEU28.228.5+0.3
BERT-LargeSQuAD v1.1F191.991.90.0
Dense versus 2:4 sparse FP16 accuracy after NVIDIA's train, prune, retrain recipe (NVIDIA Developer Blog)

Read the table across, never down. The seven rows use four different metrics (top-1 accuracy, box AP, BLEU and F1), so the only meaningful comparison is dense versus sparse within one row. Read that way the evidence is unusually broad: image classification, object detection, instance segmentation, translation and question answering, spanning convolutional networks and Transformers, and not one row lost measurable accuracy. The whitepaper's explanation is that after training "only a subset of weights have acquired a meaningful purpose", and the retraining step lets the network re-adapt around the fixed mask (NVIDIA, 2020).

Recall

Name the three steps of NVIDIA's 2:4 recipe and give one row of evidence that it holds accuracy.

Train dense, prune each group of four to its two largest magnitudes, retrain with the original schedule and the mask fixed. Evidence: BERT-Large on SQuAD v1.1 scores 91.9 F1 both dense and sparse; ResNet-50 goes from 76.1% to 76.2% top-1.

Now the coarse end of the spectrum. A convolution layer with 64 output channels is pruned at sparsity 0.5: thirty-two whole filters are deleted and the layer becomes a 32-channel layer. Nothing about the result is sparse. Its weight tensor, in the [c_o, c_i, k_h, k_w] layout of part 03, is simply smaller in the c_o dimension, and the next layer, which consumed those channels, is smaller in its c_i dimension.

That is the whole argument for channel pruning, and both sides of the slide's trade-off follow from it. Pro: direct speedup on any hardware, because a network with fewer channels does less work in every dense library that exists. Li et al. put it precisely: removing whole filters "does not result in sparse connectivity patterns", so it "does not need the support of sparse convolution libraries and can work with existing efficient BLAS libraries" (Li et al., ICLR 2017). He, Zhang and Sun report a 5x speedup on VGG-16 for a 0.3% increase in error and 2x on ResNet for 1.4% (He, Zhang and Sun, ICCV 2017). Con: a smaller compression ratio, because a channel is a much coarser unit than a weight. Keeping a channel means keeping all of its weights, including the weak ones that fine-grained pruning would have dropped, so you cannot reach the 9x to 13x of slide 20.

Pruning one layer shrinks two

The example above hid a compounding effect that the slide's bar chart depends on. Pruning the output channels of layer l removes rows from its own weight tensor and columns from layer l+1, because the input channels of l+1 are the output channels of l. The per-layer sparsity values on slide 24 therefore do not add up the way they look; they multiply through the chain.

Worked example

Five conv layers, uniform 0.3 versus the slide's per-layer sparsities

  1. Set the baseline

    Five stacked 3 x 3 layers, each 64 in and 64 out: 64 x 64 x 9 = 36,864 weights each, 184,320 in total. Layer 0's inputs come from the stem, which is not pruned, so its input columns are never removed.
  2. Write the kept fraction of one layer

    Layer l keeps (1 - s_(l-1)) x (1 - s_l) of its weights: its input columns follow the previous layer's output sparsity, its output rows follow its own.
  3. Uniform shrink, s = 0.3 everywhere

    Layer 0 keeps 0.70, every later layer keeps 0.7 x 0.7 = 0.49.
  4. Per-layer sparsities 0.5, 0.3, 0.7, 0.2, 0.3

    Layer 0 keeps 0.50, then 0.35, 0.21, 0.24, 0.56.
  5. Result

    Uniform shrink at 0.3 keeps 53.2% of the weights, uniform shrink at the per-layer set's mean of 0.4 keeps 40.8%, and the slide's per-layer set keeps 37.2%. Conv MACs scale with c_i x c_o, so the same fractions apply to compute.
LayerUniform 0.3 keptUniform 0.4 keptPer-layer kept
Layer 01.0 x 0.7 = 0.701.0 x 0.6 = 0.601.0 x 0.5 = 0.50
Layer 10.7 x 0.7 = 0.490.6 x 0.6 = 0.360.5 x 0.7 = 0.35
Layer 20.7 x 0.7 = 0.490.6 x 0.6 = 0.360.7 x 0.3 = 0.21
Layer 30.7 x 0.7 = 0.490.6 x 0.6 = 0.360.3 x 0.8 = 0.24
Layer 40.7 x 0.7 = 0.490.6 x 0.6 = 0.360.8 x 0.7 = 0.56
Total kept2.66 / 5 = 53.2%2.04 / 5 = 40.8%1.86 / 5 = 37.2%
Kept fraction per layer, (1 - input sparsity) x (1 - output sparsity)
Five layers shrink by their own ratio while the dashed line marks the uniform 0.3 cut. Layers 0 and 2 go far past it, layer 3 stops well short.

Uniform shrink versus channel prune

The inequality on slide 24, "Uniform Shrink < Channel Prune", compares accuracy at a comparable budget. Uniform shrink applies one ratio to every layer, which is what a MobileNet width multiplier does. It ignores the fact that layers differ in how much redundancy they carry: some tolerate 70% removal and others only 20%. Channel pruning proper starts from the trained wide network, chooses a ratio per layer, deletes the least useful channels in each, and fine-tunes. Under the same latency or MAC budget, spending the cuts where they hurt least keeps more accuracy. Slide 24 defers the obvious question, how to find those ratios; the sensitivity analysis of lecture 04-2 (Pruning ratios, fine-tuning and sparse hardware) and the AMC search of the next concept are the answers.

Recall

State the pro and con of channel pruning in one sentence each.

Pro: direct speedup on any hardware, because the pruned network simply has fewer channels and runs with dense kernels. Con: smaller compression ratio, because a whole channel is a coarse unit and its weak weights survive with it.

Quick check

Which granularity speeds up inference on any GPU that has only dense BLAS libraries?

On a Google Pixel 1, the full-width MobileNet takes 123.3 ms per image and scores 70.6% ImageNet top-1. Shrinking it uniformly with the 0.75 width multiplier brings the latency down to 72.3 ms but the accuracy down to 68.4%. The channel-pruned model found by AMC runs in 68.3 ms at 70.5%: as fast as the shrunken model, 2.1 points more accurate, and only 0.1 below the full model at 1.81x its speed (He et al., ECCV 2018).

AMC (AutoML for Model Compression) is the method behind the red curve on slide 25. It treats the per-layer sparsity ratios as actions for a reinforcement-learning agent, which walks the network layer by layer, proposes a ratio for each, and is rewarded by the accuracy the pruned model reaches under a FLOPs or latency constraint. The pruned model is then fine-tuned. The baseline is the easiest thing one could do instead, which the paper states plainly: "the easiest way to reduce the channels of a model is to use uniform channel shrinkage, i.e. use a width multiplier", and the result is that AMC "consistently outperforms the uniform baselines" (He et al., ECCV 2018).

ModelMMACsTop-1Pixel 1 latencySpeedup
MobileNet 1.0 (full width)56970.6%123.3 ms1.00x
MobileNet 0.75 (uniform shrink)32568.4%72.3 ms1.7x
AMC, 50% FLOPs budget28570.5%68.3 ms1.81x
AMC, 50% latency budget27270.2%63.3 ms1.95x
MobileNet on ImageNet, latency measured on a Google Pixel 1 with TensorFlow Lite (AMC, Table 4; the 0.75 row's 1.7x is computed here as 123.3 / 72.3)
AMC's curve sits above and left of the uniform width-multiplier line. At about 68 ms the vertical gap is roughly two points of ImageNet accuracy.

The chart on the slide is AMC's Figure 5b. The four table rows above are exact; the remaining points in the table below are read off the figure and are approximate. Either way the shape is the same. At equal latency the searched ratios are about 1.5 to 2 points better. At similar accuracy they are much faster: the 50% latency-budget model keeps 70.2% at 63.3 ms, 1.95x faster than the 123.3 ms full model at 70.6%, only 0.4 points higher.

CurveLatencyTop-1
Uniformabout 52 msabout 67.5%
Uniformabout 90 msabout 69.1%
AMCabout 52 msabout 69.2%
Approximate points read off AMC Figure 5b (slide 25)

Choosing a granularity for a real board

This is where the part comes together for your project. The granularity you pick is a hardware decision, not a compression decision:

  • Target is an Ampere-class or newer NVIDIA GPU (a Jetson Orin, an A100): prune to 2:4. Half the weights, about 2x on the matmuls, accuracy held by retraining.
  • Target is a phone CPU, a microcontroller or an NPU with dense kernels only: channel pruning with searched per-layer ratios, AMC style. A smaller dense network is the safest choice, since it needs no special kernels. Some mobile runtimes (XNNPACK) do accelerate high unstructured sparsity in 1x1 convolutions, so check what your runtime supports.
  • Target has a sparse accelerator such as EIE, or the constraint is storage and not latency: fine-grained pruning, for the largest compression ratio.

Quick check

Why does channel pruning with per-layer sparsities beat a uniform width multiplier at the same latency?

Recall

Give the AMC versus uniform numbers that show per-layer ratios beat uniform shrink.

On a Pixel 1, the 0.75 MobileNet gives 68.4% at 72.3 ms. AMC gives 70.5% at 68.3 ms and 70.2% at 63.3 ms, the latter 1.95x faster than the 123.3 ms full model at 70.6%.

Recap

If you remember nothing else

  • Fine-grained pruning may zero any weight, so it compresses most (AlexNet 9x, VGG-16 13x) but needs a per-weight index; only custom hardware such as EIE turns that into speed.
  • N:M sparsity keeps at most N nonzeros in every contiguous M weights; 2:4 is 50 percent sparse under either reading, but 1:4 is 75 percent (NVIDIA) versus 25 percent (slide wording).
  • A 2:4 matrix stores half its values plus 2-bit indices: 36 bits per four FP16 weights instead of 64, about 1.78x, and Ampere Sparse Tensor Cores skip the zeros for about 2x math throughput.
  • NVIDIA's train, prune to 2:4, retrain recipe held accuracy on all seven slide-22 tasks (ResNet-50 76.1 to 76.2, BERT-Large 91.9 to 91.9).
  • Channel pruning removes whole channels, so the result is a smaller dense network with direct speedup on any hardware, at the cost of a smaller compression ratio.
  • Pruning layer l's output channels also shrinks layer l+1's inputs, so per-layer channel sparsities compound in parameters and MACs.
  • Uniform shrink applies one ratio everywhere; AMC's searched per-layer ratios give 70.5 percent at 68.3 ms versus 68.4 percent at 72.3 ms for the 0.75 width MobileNet on a Pixel 1.
  • Higher sparsity is not faster inference unless the sparsity has a structure the target hardware can exploit.

Sources