COE 592Lecture 4.2Part 10
M:N sparsity on NVIDIA tensor cores
Fine-grained structured sparsity keeps exactly N nonzeros in every block of M weights, compresses the matrix to half plus two-bit indices, and lets Ampere sparse tensor cores double GEMM throughput with no accuracy loss.
- Concepts
- 4
- Slides
- 78-83
- Reading
- 24 min
Why this part matters
EIE proved that a sparse network can run faster and cooler than a dense one, but only on a chip nobody could buy. This part is the version you can run today. The same GPUs that train the models in your research project will accept a weight matrix in a fixed 2:4 pattern and double their matrix math, and NVIDIA ships the pruning recipe, the storage format and the library that does it.
Three things are worth taking from it. The exam will ask you to compute the storage of a 2:4 matrix, to explain how the tensor core uses two-bit indices to skip half its multiplies, and to justify why the accuracy tables show no loss. Beyond the exam, 2:4 is the reference point for every future claim you will read about a sparse accelerator: it is what a fixed, mild, hardware-friendly pattern buys, and where it stops.
By the end you can
- Define an a:b fine-grained structured pattern, state that 2:4 is 50 percent sparsity, and explain why a fixed count per block is what makes it hardware friendly.
- Compute the storage of a 2:4 compressed matrix (values plus 2-bit metadata) and the resulting saving for FP16 and INT8 weights.
- Trace how a sparse tensor core uses the 2-bit indices to select K/2 activations from a dense operand and halve the multiplies.
- Reproduce NVIDIA's train, prune, retrain recipe and explain why it recovers accuracy without a hyper-parameter search.
- Explain why GEMM speedup grows with K toward a 2x ceiling and why end-to-end inference gains are smaller.
Look at the first row of the structured-sparse matrix on the slide. Read it four cells at a time. The first four hold a value, a zero, a zero, a value. The next four hold a zero, a value, a value, a zero. Every group of four consecutive weights along the row has exactly two survivors, and the survivors can sit anywhere inside the group. Mishra et al. write the metadata for that row as [[0, 3], [1, 2]]: the positions of the survivors, group by group.
That is the whole definition of 2:4 sparsity: for each group of four values along a row, at least two must be zero. The general form keeps the same shape. Write a pattern as a:b, where the first number is how many weights survive and the second is the block size. Sparsity is then fixed by the pattern, not by the data.
2:4 is the instance that ships. Ampere sparse tensor cores accept it for FP16, BF16 and INT8 weights, and for TF32 the block halves to 1:2, still 50 percent (Mishra et al., section 3.2). NVIDIA describes the pattern as "two non-zero values in every four-entry vector" and calls it fine-grained structured sparsity (NVIDIA Ampere in-depth blog). The A100 whitepaper is explicit that the pattern is enforced along rows.
Fine-grained in what it removes, structured in how many
Lecture 04-1 laid out pruning granularities on a line from irregular fine-grained pruning, which may zero any single weight, to channel pruning, which removes whole filters. 2:4 sits between them and borrows the best of each. It is fine-grained because the unit removed is a single weight, so the pruning criterion still gets to pick within every block, which is why accuracy survives. It is structured because the count per block is constant, so the hardware knows in advance that every four weights hide exactly two multiplies.
That constancy is the entire engineering payoff. Unstructured sparsity, the kind EIE handles, needs a data-dependent index for every nonzero and a pointer to the start of every column, and the paper notes it leads to poor utilization of cache lines because the survivors land anywhere. With 2:4, the paper points out, the sparsity is constant across the matrix, so no indirection is required: a nonzero's position in memory can be computed directly from the compression rate. Two bits per survivor say which of the four slots it came from, and nothing else needs to be stored.
| Pattern | What can be removed | Metadata | Hardware that benefits | Flexibility for accuracy |
|---|---|---|---|---|
| Unstructured (EIE) | Any weight, anywhere | Index per nonzero, pointers, padding | Custom accelerator or slow CPU kernels | Highest, chosen per weight |
| 2:4 fine-grained structured | Any two of every four in a row | 2 bits per stored value, no pointers | Every Ampere and later GPU | High, chosen per block |
| Channel pruning | Whole output channels | None, matrix just shrinks | Any dense hardware | Lowest, chosen per channel |
One more fact will matter in the next two concepts: the groups of four run along the row of the weight matrix W. In the GEMM that a layer becomes, that row is the reduction dimension, the axis along which products are summed. The pattern has to live there, because that is the only axis on which skipping a weight also skips a multiply.
Where this sits among the three case studies
The divider slide that opens this section lists three sparse-hardware case studies. EIE (Efficient Inference Engine) came first: a custom accelerator exploiting Weight sparsity and Activation sparsity at once. This part is the middle one, and it takes the opposite bet. It exploits weight sparsity only, at a fixed and modest 50 percent, in exchange for running on a GPU that already sits in every data center. TorchSparse and PointAcc, which follow, go back to activation sparsity in point clouds. Keeping the three apart by which sparsity they exploit and what hardware they need is the fastest way to remember them.
Recall
Why is 2:4 called fine-grained structured sparsity?
Take one group of four FP16 weights. Dense, it costs 4 x 16 = 64 bits. Under 2:4, only two values are stored, 2 x 16 = 32 bits, plus a 2-bit index for each, 2 x 2 = 4 bits. The group now costs 36 bits, a saving of about 44 percent (Mishra et al., section 3.1). Not 50 percent: the indices are small but they are not free.
Scale that to a whole matrix and you get the format on the slide. A structured-sparse W of size R x C is stored as an R x C/2 block of nonzero values and an R x C/2 block of two-bit indices. The slide's instruction is to push all the nonzero elements to the left in memory. The survivors of each row are packed contiguously at half the original width, and the index block, drawn beside them, records where each came from.
Worked example
An FP16 layer of 1024 x 1024 weights
Dense storage
1024 x 1024 x 16 = 16,777,216 bits, which is 2 MiB.Stored values
Half the columns survive: 1024 x 512 = 524,288 values at 16 bits each, 8,388,608 bits = 1 MiB.Metadata
One 2-bit index per stored value: 524,288 x 2 = 1,048,576 bits = 128 KiB.Total and saving
8,388,608 + 1,048,576 = 9,437,184 bits = 1.125 MiB. The ratio to dense is 9,437,184 / 16,777,216 = 0.5625.Result
43.75% saved. The value array halves; the indices add back an eighth of what remains.
| Case | Dense | Values | Metadata | Total | Saving |
|---|---|---|---|---|---|
| FP16, R = C = 1024 | 16,777,216 (2 MiB) | 8,388,608 (1 MiB) | 1,048,576 (128 KiB) | 9,437,184 (1.125 MiB) | 43.75% |
| INT8, R = C = 4096 | 134,217,728 (16 MiB) | 67,108,864 (8 MiB) | 16,777,216 (2 MiB) | 83,886,080 (10 MiB) | 37.5% |
The index cost is a fixed 2 bits per stored value, so its weight relative to the values depends on the value width: 2 / 16 = 12.5% overhead for FP16 and 2 / 8 = 25% for INT8, which is why the INT8 saving is the smaller 37.5 percent (Mishra et al., section 3.1). Compare that with the format EIE relied on. CSC stores a 4-bit relative index and a 4-bit weight-sharing code per nonzero, a 16-bit pointer per column, and a padding entry whenever a run of zeros exceeds fifteen (Han et al., EIE, section III). Mishra et al. note that a plain CSR with 8-bit weights and 16-bit column indices can spend up to 200 percent of the value bits on metadata. 2:4 spends 12.5 or 25 percent, with no pointers and no padding, because the pattern itself carries most of the position information.
One group of four weights under 2:4
- FP16 dense
- 4 x 16 = 64 bits
- FP16 compressed
- 2 x 16 + 2 x 2 = 36 bits, about 44% saved
- INT8 dense
- 4 x 8 = 32 bits
- INT8 compressed
- 2 x 8 + 2 x 2 = 20 bits, about 38% saved
Why insist on pushing everything to the left rather than leaving zeros in place and skipping them? Because memory is read in wide lines. With the survivors contiguous at half width, every byte a memory read brings in is a value the tensor core will use, which the paper describes as letting hardware fully utilize large memory reads. The A100 whitepaper puts the same point as a reduction of memory storage and bandwidth by almost 2x. Zeros left in place would fill half of every line with nothing.
Check against Mishra et al.: 43.75 percent, the paper's about 44 percent for FP16.
The value array always halves under 2:4, but every stored value drags a 2-bit index with it, so the saving lands at 43.75 percent for 16-bit weights and 37.5 percent for 8-bit weights, never at 50. The MAC count halves exactly, which is the 2x the sparse tensor core can deliver on the matrix math alone. The last readout applies Amdahl to the whole network: with 70 percent of inference time inside GEMMs and a measured 1.8x on those GEMMs, the model runs about 1.45x faster. Drag the GEMM share down to see why memory-bound layers and small batches hide most of the gain.
Quick check
A 2:4 sparse FP16 weight matrix has R = 512 rows and C = 1024 columns. How many metadata bits does the compressed format hold?
Recall
For an R x C weight matrix in 2:4 format, how many values and how many metadata bits are stored?
Follow one output element through a small GEMM with K = 8. Dense, the tensor core takes a row of A with eight values, a column of B with eight values, multiplies them pairwise and accumulates eight products. Now store that row of A in 2:4 form: four values and four 2-bit indices. The core reads the indices, pulls exactly the four elements of the B column that sit at those positions, multiplies four pairs, and accumulates. The slide's caption says it in one line: the indices are used to mask out the inputs, and only two multiplications will be done out of four.
The rule behind the example is worth stating precisely, because exam questions turn on it. A Sparse tensor core performs sparse matrix times dense matrix equals dense matrix. Only the first operand, A of size M x K, is compressed, to M x K/2 values plus indices. The second operand B (K x N) and the output C (M x N) stay dense (Mishra et al., section 3.2). NVIDIA's TensorRT blog describes the mechanism as using the metadata to pull only the necessary values from the other, uncompressed operand. The metadata belongs to the weights, but it is applied to the activations.
The weight row, already packed left.
A multiplexer over the dense B column.
Writes a dense element of C.
Halving the pairs halves the work, and the hardware is built so that the saving shows up as time. The A100 whitepaper states that a standard MMA on a 16 x 8 x 16 tile takes some number of cycles N, and the sparse MMA on the same tile takes N/2, a 2x speedup. The paper's Table 1 reports the resulting peak rates.
A100 peak dense versus sparse tensor throughput, in TOPS (Mishra et al., Table 1)
- TF32 (1:2 pattern)
- 156 dense, 312 sparse
- FP16 / BF16
- 312 dense, 624 sparse
- INT8
- 624 dense, 1248 sparse
Why must the pattern run along K? Because K is the axis the selector walks. Each output element is a dot product over K, and a zero weight at position k means the product with B[k, n] can be dropped for every n. Zeros arranged along M or N would zero entire rows or columns of the output, which is a smaller network, not a faster GEMM. This is also why the library has shape rules: the reduction dimension must be a multiple of 16 for 16-bit formats and 32 for INT8, and layers that fail the rule, such as the first convolution of an image network with K = 3 x 7 x 7 = 147, are simply left dense (Mishra et al., sections 3.2 and 5.1). cuSPARSELt exposes the compression and the sparse GEMM to programmers, and TensorRT 8 applies them automatically to a network whose weights already follow the pattern.
What changed since EIE
Set the two designs beside each other and the trade becomes visible. EIE (Efficient Inference Engine) reaches for every zero it can find: about 90 percent in the weights and about 70 percent in the activations, both exploited at once. To do that it needs Leading non-zero detection to find the next live activation, a FIFO in front of each Processing element (PE) to keep Load balance across uneven columns, and a custom chip to hold all of it. The sparse tensor core asks for far less sparsity, exactly 50 percent in the weights alone, which is static and known before the run. That is what lets the whole mechanism collapse into a multiplexer driven by 2-bit tags, small enough to add to a tensor core that every GPU already has.
| Aspect | EIE (ISCA 2016) | 2:4 sparse tensor core (2020) |
|---|---|---|
| Sparsity exploited | Weights (about 90 percent) and activations (about 70 percent) | Weights only, exactly 50 percent |
| Weight format | CSC: 4-bit relative index plus 4-bit code per nonzero, column pointers, padding | Contiguous values plus one 2-bit index per stored value |
| Finding work | Leading nonzero detection, activation FIFO for load balance | Multiplexer driven by the 2-bit indices, no search |
| Hardware | Custom 45 nm ASIC, never sold | Every Ampere or later GPU, cuSPARSELt and TensorRT |
| Ceiling on math | Proportional to combined sparsity | 2x, fixed by the pattern |
Quick check
Which statement about 2:4 sparse GEMMs on Ampere sparse tensor cores is correct?
Quick check
Compared with EIE, what makes 2:4 sparsity easy to deploy on commodity hardware?
Recall
Which GEMM operand is stored sparse, which is dense, and along which dimension must the 2:4 pattern run?
ResNet-50 on ImageNet scores 76.1 top-1 dense in FP16. After 2:4 pruning and retraining it scores 76.2 in FP16 and 76.2 in INT8 (Mishra et al., Table 2). Half the weights are gone from almost every layer, the GEMMs can run on the sparse path, and the accuracy did not move. The slide's takeaway is the plain version of this: pruning CNNs with 2:4 sparsity brings a large speedup for GEMM workloads and does not incur a performance drop for the models. The rest of this concept explains how that is achieved, how large the speedup really is, and where both claims stop.
The recipe: one prune, one retrain, no search
The deck does not show the procedure itself, so take it from the paper (Mishra et al., section 4) and from the A100 whitepaper, which calls it a simple and universal recipe. It has three steps.
- Train the model without sparsity, exactly as you normally would.
- Prune it to 2:4 by magnitude: in every group of four weights along the row, zero the two with the smallest absolute value.
- Retrain from those weights using the same optimizer, learning-rate schedule and number of epochs as step 1, with the zeros held fixed so the pattern survives. Optimizer state such as momentum is reset.
Two things distinguish this from the Fine-tuning and Iterative pruning you met earlier in this lecture. It is one-shot: a single prune straight to the target, then a full second training run rather than a short low-learning-rate touch-up. And it needs no hyper-parameter search, because step 3 reuses step 1 wholesale. The paper is candid about the cost, a second full training, and argues it is worth paying once for a workflow with nothing to tune, since deployment amortizes it. NVIDIA packages the procedure as the ASP library for PyTorch.
How much faster: a staircase toward 2x
The chart on the slide compares INT8 GEMMs from cuSPARSELt, with one operand in 2:4 form, against dense cuBLAS GEMMs on an A100, at M = N = 10240 and K sweeping from 1280 to 20480. The bars start near 1.2x and climb toward 2x without reaching it. Mishra et al. read it the same way: larger GEMMs achieve nearly a 2x speedup with sparse tensor cores.
| GEMM-K | Speedup |
|---|---|
| 1280 | about 1.2x |
| 2560 | about 1.5x |
| 3840 | about 1.7x |
| 7680 | about 1.8x |
| 12800 | about 1.9x |
| 20480 | about 1.95x |
Why does the speedup depend on K at all, when the pattern halves the multiplies at every size? Because the sparse tensor core halves only the arithmetic. A GEMM also has to move its operands in and its result out, and it pays fixed launch and scheduling costs. A small GEMM has low arithmetic intensity: few operations per byte moved, so its time is dominated by memory traffic and overheads that 2:4 does not touch. As K grows, the operations per output element grow while the output traffic does not, the GEMM becomes math bound, and halving the math approaches halving the time. The paper says exactly this: larger GEMMs tend to have higher arithmetic intensity, so they get closer to the 2x speedup.
Worked example
From GEMM speedup to model speedup with Amdahl
Name the fraction that improves
Suppose GEMMs take 70% of inference time (f = 0.7) and the sparse path makes them 1.8x faster (k = 1.8), a typical large-K reading from the chart.Apply Amdahl's law
S = 1 / ((1 - 0.7) + 0.7 / 1.8) = 1 / (0.3 + 0.389) = 1 / 0.689.Repeat for a small-K layer
With k = 1.2 the GEMM term is 0.7 / 1.2 = 0.583, so S = 1 / 0.883 = 1.13x.Result
About 1.45x end to end at 1.8x on the GEMMs, and only 1.13x when the GEMMs are small. The pattern is doing its job on the math either way; the rest of the network decides what the user sees.
Accuracy: the table that justifies the claim
The right half of the slide is the paper's Table 2: twenty ImageNet classifiers, each in dense FP16, sparse FP16 and sparse INT8. Read down any row and the three numbers agree to within a few tenths of a point; the widest spread is SUNet-128 at 75.6, 76.0 and 75.4. The paper states that the differences are within run-to-run variation, which is the honest way to say zero loss.
| Network | Dense FP16 | Sparse FP16 | Sparse INT8 |
|---|---|---|---|
| ResNet-34 | 73.7 | 73.9 | 73.7 |
| ResNet-50 | 76.1 | 76.2 | 76.2 |
| ResNet-101 | 77.7 | 78.0 | 77.9 |
| ResNeXt-101-32x16 (WSL) | 84.2 | 84.0 | 84.2 |
| DenseNet-121 | 75.5 | 75.3 | 75.3 |
| Inception v3 | 77.1 | 77.1 | 77.1 |
| VGG-16 | 74.0 | 74.1 | 74.1 |
| DRN-105 | 79.4 | 79.5 | 79.4 |
Two details in that table repay attention. Sparse INT8 matches sparse FP16, so the pruning and INT8 quantization, which this course turns to after pruning, compose without compounding their losses, at least on these networks. And the largest model, ResNeXt-101-32x16 trained with weak supervision, loses 0.2 in FP16 and nothing in INT8, so the pattern is not exploiting a weakness of small or old architectures. VGG, DenseNet, Inception, Xception and the dilated residual networks all behave the same way.
| Network | Dense | 2:4, plain recipe | 2:4 with permutation |
|---|---|---|---|
| MobileNet v2 | 71.55 | 69.56 | 71.56 |
| EfficientNet B0 | 77.25 | 75.98 | 77.29 |
Quick check
On the A100 chart, why does the sparse versus dense INT8 GEMM speedup climb toward 2x only as GEMM-K grows?
Recall
State the three steps of NVIDIA's 2:4 recipe and the one hyper-parameter search it needs.
Recall
Why is the INT8 speedup only about 1.2x at K = 1280 but about 1.95x at K = 20480?
Recap
If you remember nothing else
- 2:4 keeps at most two nonzeros in every four consecutive weights along a row: 50 percent sparsity, fine-grained in what it removes, structured in how many it removes.
- Compressed W = R x C/2 values plus R x C/2 two-bit indices. Per group of four, 64 bits become 36 (FP16, about 44 percent saving) and 32 become 20 (INT8, about 38 percent).
- The pattern runs along GEMM-K. The sparse tensor core uses the indices to pick K/2 matching elements of the dense B operand, so only half the multiplies run.
- Peak A100 throughput doubles: FP16 312 to 624 TOPS, INT8 624 to 1248 TOPS.
- Recipe: train dense, prune the two smallest of every four, retrain with the identical schedule keeping the zeros fixed. No hyper-parameter search.
- Sparse FP16 and INT8 match dense FP16 within run-to-run noise on 20 ImageNet CNNs (ResNet-50 76.1 versus 76.2). Small nets like MobileNet v2 need channel permutation to recover.
- INT8 GEMM speedup rises from about 1.2x at K = 1280 to about 1.95x at K = 20480. The 2x caps the math only; end-to-end gains are smaller (about 1.2x for ResNeXt-101 in NVIDIA's blog).
- Versus EIE: a fixed pattern and 2-bit tags on a commodity GPU instead of per-value indices, load balancing and a custom ASIC.
Sources
- Accelerating Sparse Deep Neural NetworksPaperMishra, Albericio Latorre, Pool, Stosic, Stosic, Venkatesh, Yu and Micikevicius, arXiv 20212:4 definition and Fig. 1 format, 36 versus 64 bits, Fig. 2 mapping onto tensor cores, Table 1 TOPS, Fig. 3 speedups, Section 4 recipe, Table 2 accuracy, Table 3 permutation.(opens in a new tab)
- Accelerating Inference with Sparsity Using the NVIDIA Ampere Architecture and NVIDIA TensorRTArticleNVIDIA Technical BlogThree-step recipe, pulling only the necessary values from the uncompressed operand, 1248 versus 624 INT8 TOPS, ResNeXt-101_32x8d up to 20 percent end to end and 36 percent performance per watt.(opens in a new tab)
- NVIDIA Ampere Architecture In-DepthArticleNVIDIA Technical BlogFine-grained structured sparsity, two nonzero values in every four-entry vector, almost 2x memory reduction and doubled tensor core throughput.(opens in a new tab)
- NVIDIA A100 Tensor Core GPU Architecture whitepaperDocsNVIDIASparse MMA on a 16 x 8 x 16 tile in N/2 cycles, 2:4 structured sparsity on rows, the simple and universal recipe.(opens in a new tab)
- cuSPARSELt documentationDocsNVIDIALibrary for GEMMs where one operand is 50 percent structured sparse; FP16, BF16, INT8 and TF32 on SM 8.0 and later, FP8 from SM 9.0.(opens in a new tab)
- EIE: Efficient Inference Engine on Compressed Deep Neural NetworkPaperHan, Liu, Mao, Pu, Pedram, Horowitz and Dally, ISCA 2016CSC with 4-bit relative index and 4-bit weight-sharing code, activation queue for load balance, custom 45 nm ASIC, used for the contrast.(opens in a new tab)
- MIT 6.5940 TinyML and Efficient Deep Learning Computing, Fall 2024, Lecture 4: Pruning and Sparsity (Part II)DocsMIT HAN LabThe course these slides follow.(opens in a new tab)
- Validity of the Single Processor Approach to Achieving Large Scale Computing CapabilitiesPaperAFIPS Conference Proceedings, Vol. 30, 1967The argument behind the end-to-end speedup worked example.(opens in a new tab)