Majid Al-RaimiEIE: the first accelerator for sparse, compressed networks

COE 592Lecture 4.2Part 07

EIE: the first accelerator for sparse, compressed networks

Why sparsity needs hardware support, Han's co-design paradigm, and how EIE exploits weight sparsity, activation sparsity and weight sharing by splitting a sparse matrix-vector product across processing elements.

Concepts
3
Slides
53-60
Reading
18 min
Understood
0/3 concepts

Why this part matters

Parts 02 to 06 chose pruning ratios and recovered accuracy. They never asked the uncomfortable question: after you remove 90 percent of the weights, is the network actually faster? On a GPU the honest answer is often no, and sometimes it is slower. This part explains why, and shows what hardware must do for pruning to become speed and energy.

The vehicle is EIE, the Efficient Inference Engine from Han et al. at ISCA 2016, the first accelerator built to run directly on a pruned, quantized model. You will learn its three sources of savings with the exact numbers on the slide, why one of them is dynamic and the other two static, and how a sparse matrix-vector product is split across processing elements so that zero weights are never stored and zero activations are never multiplied. This is the bridge to the M:N tensor cores and point-cloud engines later in the lecture, to the exam question "explain EIE's three savings and its PE dataflow", and to any research project that deploys a pruned model on an embedded accelerator.

By the end you can

  1. Explain, with the EIE paper's Table IV numbers, why fine-grained sparsity gives little or even negative speedup on CPUs and GPUs.
  2. Name the three systems on slide 54 and the kind of sparsity each one exploits.
  3. State EIE's three sources of savings with their sparsity or bit width and their computation and memory factors, and explain the 5x versus 10x gap.
  4. Distinguish static from dynamic sparsity and say why ReLU makes activation sparsity dynamic.
  5. Draw the 8 x 4 example: assign rows to PEs round-robin, broadcast the nonzero activations, and count the multiplications that actually happen.

Take AlexNet's FC6 layer, a 9216 x 4096 matrix that Han's Pruning left 91 percent zeros. Feed it one input vector. The EIE paper timed exactly this layer on a desktop CPU and a Titan X GPU, once with the dense matrix and once with the sparse one stored in a compressed format and run through the vendor's sparse kernels (MKL and cuSPARSE). The results are the whole motivation for this part.

PlatformBatchDense matrixSparse matrixSparse versus dense
Core i7-5930k CPU17516.2 μs3066.5 μs2.5x faster
GeForce Titan X GPU1541.5 μs134.8 μs4.0x faster
GeForce Titan X GPU6419.8 μs94.6 μs4.8x slower
EIE, 64 PEs1runs only the sparse form30.3 μs248x vs dense CPU
AlexNet FC6, one layer, wall-clock time from EIE Table IV (Han et al., 2016)

Removing 91 percent of the multiplications bought only 2.5x on the CPU and 4x on the GPU, not the 11x the arithmetic promises. Worse, once the GPU batches 64 inputs so that the dense kernel can use its full width, the sparse kernel falls 4.8x behind. The paper's summary is blunt: "the irregular pattern caused by compression hinders the effective acceleration on CPUs and GPUs". A general-purpose core cannot skip a zero for free. It has to read an index, compute an address, gather a scattered activation and suffer the cache miss, and that bookkeeping costs more than the multiply it avoided. Custom accelerators before EIE did no better: sparse matrix-vector (SpMV) engines from scientific computing handle the static zeros in the weights but not the run-time zeros in the activations, and DNN accelerators of the day "must expand the network to dense form" before they can run it.

Why memory is the real enemy

Operation (45 nm)EnergyRelative to SRAM read
32-bit SRAM read5 pJ1x
32-bit DRAM read640 pJ128x
32-bit float multiply3.7 pJabout 0.7x
Energy per operation in the 45 nm process the paper uses for its estimates (EIE Table I)

The table is the second half of the argument, the one that decides whether a model can run on a phone at all: the 128x gap between an on-chip and an off-chip read dwarfs the multiply itself. A network with one billion connections evaluated at 20 Hz spends 20 x 10^9 x 640 pJ = 12.8 W on DRAM traffic alone, far past any mobile power budget. The lesson that Deep Compression drew from this is that the goal is not fewer FLOPs but a model small enough to live entirely in SRAM: AlexNet shrinks from 240 MB to 6.9 MB and VGG-16 from 552 MB to 11.3 MB, both with no loss of accuracy. Once the whole model fits on chip, every weight read is the cheap kind.

This is the point at which the five questions of the outline slide (what pruning is and how to formulate it, which granularity, which criterion, what ratio per layer, and how to fine-tune) hand over to a sixth that the outline never lists: on what hardware. All five are now answered, in lecture 04-1 and in parts 02 to 06 here, and the constraint ||W_P||_0 <= N has produced a model with few nonzeros. The rest of the lecture is about turning that small N into small time and small energy.

Han's paradigm: co-design the compression and the engine

Slide 56 draws the conventional flow as training on a server, then a big network shipped to a phone for slow, power-hungry inference. The proposed flow inserts a model compression stage between them and replaces the phone's generic processor with accelerated inference. The labels under each stage are five papers by the same group, and reading them as a set is the fastest way to see that compression and the engine were designed together. Neither is useful alone: a compressed model on a GPU gives the Table IV numbers above, and an engine for sparse models with nothing sparse to run is idle silicon. Together they deliver what the slide calls fast and power efficient: EIE with 64 PEs at 800 MHz draws about 600 mW and beats both baselines on the same nine FC and LSTM benchmarks by the margins below.

EIE versusSpeedupEnergy efficiency
Core i7-5930k CPU189x24,000x
Titan X GPU13x3,400x
EIE against the two baselines on the nine FC and LSTM benchmarks (Han et al., 2016)
The conventional lane ships the full network to a generic processor. The proposed lane clamps it down through pruning, quantization and Huffman coding, then hands the small model to an engine built for it.

The five paper labels on slide 56

ICLR 2017, under Training
DSD: dense-sparse-dense training, a regularizer that prunes and regrows during training to reach a better dense model
NeurIPS 2015, under Model Compression
Learning both Weights and Connections: train, prune, retrain, giving 9x fewer AlexNet and 13x fewer VGG-16 parameters without accuracy loss
ICLR 2016 best paper, under Model Compression
Deep Compression: pruning, trained quantization with a k-means codebook, then Huffman coding; AlexNet 240 MB to 6.9 MB (35x), VGG-16 552 MB to 11.3 MB (49x)
ISCA 2016, under Accelerated Inference
EIE: the ASIC that runs directly on the pruned, codebook-quantized weights
FPGA 2017 best paper, under Accelerated Inference
ESE: the same idea for sparse LSTMs on a Xilinx XCKU060 FPGA, 20x compression and 282 GOPS with load-balance-aware pruning

Three systems, three kinds of sparsity

Slide 54 lists the hardware this section covers, and each entry targets a different sparsity. EIE exploits Weight sparsity and Activation sparsity at the same time, which is what made it the first of its kind. The NVIDIA sparse tensor core accepts only structured M:N sparsity, trading flexibility for a dense-friendly pattern. TorchSparse and PointAcc exploit activation sparsity of a very different origin: point clouds are mostly empty space, so the zeros are in the input, not in the weights.

Roadmap for the rest of the lecture, from slide 54

EIE (Han et al., ISCA 2016)
Weight sparsity plus activation sparsity in fully connected layers, on a custom ASIC. This part and parts 08 and 09.
NVIDIA Tensor Core (Ampere)
M:N weight sparsity, specifically 2:4: two of every four consecutive weights must be zero, and the hardware skips the matching activations. Part 10.
TorchSparse and PointAcc
Activation sparsity of point clouds, where most voxels are empty, handled by sparse convolution on GPUs and on a custom accelerator. Parts 11 to 13.

Recall

Why does a 91 percent sparse FC6 layer run only 2.5x faster on a CPU, and slower than dense on a GPU at batch 64?

The zeros are removed from the arithmetic but the surviving weights are scattered irregularly. A CPU or GPU must read indices, gather activations and take cache misses for each one, which costs more than the multiplies it skips. At batch 64 the dense kernel fills the GPU's wide units while the sparse kernel cannot, so it is 4.8x slower.

Recall

Name the three systems on slide 54 and the sparsity each exploits.

EIE: weight sparsity plus activation sparsity in fully connected layers. NVIDIA Tensor Core: M:N (2:4) structured weight sparsity. TorchSparse and PointAcc: activation sparsity of point clouds through sparse convolution.

Look at one fully connected layer of AlexNet, FC7, a 4096 x 4096 matrix of 16.8 M weights that occupies 64 MB in 32-bit floating point. A dense engine stores all 16.8 M values and performs 16.8 M multiply-accumulate operations (MACs) for every input. After Deep Compression, the EIE paper reports that only 9% of the weights survive, about 35% of the input activations are nonzero, and 3% of the original FLOPs remain. EIE reaches that 3 percent by combining three savings that the slide states in round numbers.

Each full bar is the dense cost. On hover the sparse-weight bar shrinks to a tenth, the sparse-activation bar to a third and the weight-sharing bar to an eighth, with the rule of thumb behind each.
SourceSparsity or bitsComputation savingMemory savingRule of thumb
Sparse weight90% static sparsity10x less computation5x less memory footprint0 x A = 0
Sparse activation70% dynamic sparsity3x less computationnone claimed on the slideW x 0 = 0
Weight sharing4-bit weightsnone claimed on the slide8x less memory footprint2.09, 1.92 => 2
The three savings as stated on slide 57

The first column is Weight sparsity. Pruning zeroed about 90 percent of the matrix, so a product 0 x A is known to be zero without looking at A. An engine that never stores those weights skips their multiplications for free, hence 10x less computation. The second column is Activation sparsity. About 70 percent of the input vector is zero because it came out of a ReLU, so W x 0 is also known without looking at W. Skipping those columns removes another factor of roughly 1 / 0.3 = 3.3, which the slide rounds to 3x, and the paper measures that skipping them saves about 65 percent of the computation cycles. The third column is Weight sharing: the surviving weights are not stored as32-bit floats but as 4-bit indices into a per-layer codebook of 2^4 = 16 shared values, which is where the crossed-out 2.09, 1.92 => 2 comes from. Both weights snap to the same centroid and are stored as the same index, and 32 / 4 is the 8x memory saving.

bi=ReLU(jXiYS[Iij]aj)b_i = \mathrm{ReLU}\Big(\sum_{j \in X_i \cap Y} S[I_{ij}]\, a_j\Big)
EIE's compressed layer (paper eq. 3): X_i is the static set of nonzero columns in row i, Y the dynamic set of nonzero activations, S the 16-entry codebook, I_ij the 4-bit index

The formula packs all three savings into one line. The sum runs only over X_i ∩ Y, the columns that are nonzero in both the weight row and the activation vector, which is the 10x and the 3x. Each weight appears as S[I_ij], a codebook lookup, which is the 8x. The two computation factors multiply to 10 x 3 = 30x, which is why the paper can describe 102 GOPS (giga operations per second) of work on the compressed network as about 3 TOPS (tera operations per second) on the uncompressed one. The 8x from the codebook is a memory factor and does not reduce the operation count.

Why memory shrinks 5x and not 10x

The one number that trips students is the 5x. Ten percent of the weights survive, so why not 10x less memory? Because a nonzero that is stored without its neighbors must carry its position. EIE stores each surviving weight together with a 4-bit relative index (the number of zeros since the previous nonzero in the column), a scheme explained fully in part 08 under Compressed sparse column (CSC). The retrospective on the paper states it directly: "the weight and index are both 4bit giving a 50% storage overhead". Half of every stored entry is bookkeeping, so the 10x from sparsity is halved to 5x. Computation keeps its full 10x, since the index is read but never multiplied.

Worked example

From 3200 bits to 80 bits

  1. Dense storage

    100 weights in 32-bit floating point occupy 100 x 32 = 3200 bits.
  2. Prune to 10 percent, keep full precision

    10 survivors, each with a 32-bit value plus a 32-bit position: 10 x 64 = 640 bits. That is 3200 / 640 = 5x, which is the slide's sparsity row: the index costs as much as the value.
  3. Add weight sharing

    Weight sharing drops the value to a 4-bit codebook index (32 / 4 = 8x). EIE also keeps the position the same width as the value, a 4-bit relative index, so the index overhead stays at 2x and the 5x from step 2 holds: 10 x (4 + 4) = 80 bits. Relative to the 640-bit step this is 8x, the slide's weight-sharing row.
  4. 40x overall

    3200 / 80 = 40x, which is exactly 5 x 8. The decomposition assumes the index is as wide as the value, which is how EIE stores it: the slide assigns the index overhead to the sparsity factor and the bit-width gain to the sharing factor, and the two multiply.

Static versus dynamic

The italic words on the slide, static and dynamic, are the conceptual core of this part and the key to Static versus dynamic sparsity. The paper defines X_i as the set of columns where row i of W is nonzero and Y as the set of indices where a is nonzero, then says: "The set X_i is fixed for a given model. The set Y varies from input to input." Weight zeros are decided once, when pruning and Fine-tuning finish, so the storage format can be laid out offline with every zero already gone. Activation zeros are made fresh by ReLU for every input, since a different image produces a different set of negative pre-activations. No format can remove them in advance; the engine must find them at run time, which is the job of the Leading non-zero detection unit in part 08.

What the two words on the slide mean

Static sparsity (weights)
The set X_i of columns where row i has a nonzero is fixed once pruning and fine-tuning finish. It can be encoded offline into the storage format and never changes from input to input.
Dynamic sparsity (activations)
The set Y of indices where a_j is nonzero depends on this input: ReLU zeroed whatever came out negative. It must be detected at run time by scanning the vector.

The four factors behind the paper's 28,800x energy figure

SRAM instead of DRAM
120x
Weight sparsity
10x
Weight sharing
8x
Skipped activations
3x
Product
120 x 10 x 8 x 3 = 28,800x

Quick check

Which of EIE's savings is dynamic, meaning it depends on the input at run time?

Quick check

Why does 90 percent weight sparsity cut EIE's memory only 5x while cutting computation 10x?

Recall

State EIE's three sources of savings with the numbers on slide 57.

Sparse weights, 90 percent static sparsity, 10x less computation and 5x less memory. Sparse activations, 70 percent dynamic sparsity, 3x less computation. Weight sharing with 4-bit weights, 8x less memory.

Recall

Why is activation sparsity called dynamic while weight sparsity is static?

Weight zeros are fixed once pruning and fine-tuning finish, so the set X_i is known before deployment. Activation zeros come from ReLU acting on this input, so the set Y changes from input to input and must be detected at run time.

Slides 58 to 60 show the same small figure three times, and it is worth working it with real numbers before reading the rule. The input is a = (0, a1, 0, a3), the weight matrix is 8 x 4 with eleven nonzeros, and there are four processing elements. Give the symbols values: a = (0, 2, 0, 1), and in the matrix w00 = 1, w01 = 3, w03 = -2, w12 = 5, w21 = -1, w23 = 1, row 3 empty, w42 = 2, w43 = -3, w50 = 6, w63 = 2, w71 = -4. The colors on the slide say who owns what: row 0 is PE0, row 1 is PE1, row 2 is PE2, row 3 is PE3, and row 4 wraps around to PE0 again.

Worked example

Two broadcasts, seven multiplications

  1. Scan a for its first nonzero

    a0 = 0, so column 0 is skipped for every PE at once. The first nonzero is a1 = 2, and the controller broadcasts the pair (2, j = 1) to all four PEs.
  2. Each PE works column 1 of its own rows

    PE0 holds w01 = 3: b0 += 3 x 2 = 6. PE2 holds w21 = -1: b2 += -2. PE3 holds w71 = -4: b7 += -8. PE1 has no nonzero in column 1 and does nothing.
  3. Scan on and broadcast a3

    a2 = 0, so column 2 is skipped, and with it w12 and w42, which are never read. The next nonzero is a3 = 1, broadcast as (1, j = 3).
  4. Each PE works column 3

    PE0: b0 += -2 x 1, giving 4; and b4 += -3 x 1 = -3. PE2: b2 += 1 x 1, giving -1; and b6 += 2 x 1 = 2. PE1 and PE3 have nothing in column 3.
  5. ReLU inside each PE

    b = (4, 0, -1, 0, -3, 0, 2, -8) becomes (4, 0, 0, 0, 0, 0, 2, 0). The negative rows 2, 4 and 7 are the ones the slide draws as -b2, -b4, -b7 and zeroes after ReLU.
  6. 7 multiplications instead of 32

    The dense product needs 8 x 4 = 32 MACs. EIE performs 7, a 4.6x reduction, stores 11 weights instead of 32, and never touches columns 0 and 2.
The 8 x 4 matrix with rows colored by PE. On hover the zero activations dim and strike through, columns 1 and 3 light up, each nonzero weight sends its product along its own row into b, and ReLU zeroes the three negative rows.
PERows ownedNonzero weights storedMACs performedOutputs before ReLU
PE00, 453 (w01, w03, w43)b0 = 4, b4 = -3
PE11, 520 (columns 0 and 2 skipped)b1 = 0, b5 = 0
PE22, 633 (w21, w23, w63)b2 = -1, b6 = 2
PE33, 711 (w71)b3 = 0, b7 = -8
Total8 rows11 of 327 of 32 dense MACsReLU keeps b0 = 4 and b6 = 2
What each PE stores and does in the worked example

The rule: interleave rows, broadcast activations

The paper states the partition in one sentence: with N PEs, "PE_k holds all rows W_i, output activationsb_i, and input activations a_i for which i (mod N) = k". Rows are dealt out round-robin like cards, so PE0 gets rows 0, 4, 8 and so on. Each PE keeps only the nonzeros of its rows, in its own CSC arrays and its own SRAM, so no PE ever sees the full matrix and no zero weight is stored anywhere. That is the rule of thumb 0 x A = 0 made physical. On the left of slide 58 the same idea appears as hardware: a grid of identical PEs wired to one central control unit that does the scanning and broadcasting (the slide draws 16; the EIE configuration evaluated in the paper uses 64).

PE(i)=imodN,bi=ReLU(jYWijaj),Y={j:aj0}\mathrm{PE}(i) = i \bmod N, \qquad b_i = \mathrm{ReLU}\Big(\sum_{j \in Y} W_{ij}\, a_j\Big),\quad Y = \{\, j : a_j \neq 0 \,\}
Row ownership and the per-PE accumulation over nonzero activations only

The dataflow follows from the ownership. The paper describes it as "scanning vector a to find its next non-zero value a_j and broadcasting a_j along with its index j to all PEs. Each PE then multiplies a_j by the non-zero elements in its portion of column W_j, accumulating the partial sums in accumulators for each element of the output activation vector b." The broadcast is necessary because a_j lives in a column, and a column cuts across every PE's rows: any of the four might hold a nonzero in column j, and only the PE that owns row i is allowed to update b_i. The reward is that every output belongs to exactly one PE, so there is no reduction step between PEs at the end. The paper weighs this explicitly among three ways to partition the matrix and concludes that distributing rows gives "full locality for vector b. The drawback is that vector a needs to be broadcast". The broadcast is cheap: a is about 4 K long and about 30 percent dense, so around 1.2 K broadcasts per layer, each followed by many cycles of local work, and FIFOs decouple the controller from the PEs so the broadcast is not on the critical path.

Zero activations, the Activation sparsity of the previous concept, are handled by the scan itself. A zero is never broadcast, so its whole column is skipped for all N PEs in one decision, which is W x 0 = 0 made physical and what slide 60 highlights by boxing a0 = 0. In part 08 that scan is the Leading non-zero detection unit, and the word "logically" on slide 59 is a reminder that the tidy 8 x 4 grid is the logical view only. Physically PE0 holds a compressed slice with five entries and never sees the zeros that the figure draws.

SimulatorEIE sparse matrix-vector stepper: four PEs, one broadcast at a time
Click any weight to step it through 0, 2, -3, 1 (other values reset to 0), and any activation through 0, 1, 2, 3. Editing resets the broadcast schedule.
a
no broadcast yet
row 0 PE0
b00ReLU0
row 1 PE1
b10ReLU0
row 2 PE2
b20ReLU0
row 3 PE3
b30ReLU0
row 4 PE0
b40ReLU0
row 5 PE1
b50ReLU0
row 6 PE2
b60ReLU0
row 7 PE3
b70ReLU0
  • PE0rows 0, 4idle this broadcast5 stored0 MACs so far
  • PE1rows 1, 5idle this broadcast2 stored0 MACs so far
  • PE2rows 2, 6idle this broadcast3 stored0 MACs so far
  • PE3rows 3, 7idle this broadcast1 stored0 MACs so far
MACs7 of 324.6x fewer than dense
Weights stored11 of 32zeros are never written to SRAM
Columns skipped2 of 4zero activations never broadcast
Busiest PE3 vs 1.75imbalance 1.7x across 4 PEs

Row i belongs to PE (i mod 4), so each output b_i is accumulated inside exactly one PE and no result ever crosses between PEs. The controller scans a for its next nonzero, broadcasts that value with its column index, and every PE multiplies it by the nonzero weights it holds in that column. A zero activation means the whole column is skipped for all four PEs at once, and a zero weight was never stored, so neither rule of thumb costs a cycle. The imbalance readout shows the price: whichever PE holds the most nonzeros in the broadcast column sets the pace.

Why interleave rather than block

The paper weighs three partitions (Section VII-A). Splitting by columns gives each a_j to one PE but needs a reduction across PEs and becomes unbalanced because a is 70 percent zero. 2D blocks need both a broadcast and a reduction. Splitting by rows keeps each b_i local and costs only one broadcast per column. Dealing rows out round-robin (rather than in contiguous blocks, a choice the paper does not justify explicitly) spreads each column's nonzeros across PEs. The small example already shows the residual problem: column 3 gives PE0 and PE2 two multiplications each while PE1 and PE3 get none, and over the whole product PE1 does nothing at all. The busiest PE sets the pace of every broadcast. This is the Load balance issue that the activation queue in part 08 softens by letting PEs run ahead, and that ESE later attacked at pruning time.

Quick check

In EIE, how are the rows of the weight matrix assigned to processing elements?

Quick check

The central control unit finds a nonzero activation a_j. What does EIE do with it?

Recall

In EIE with N PEs, which PE holds row i, and what happens when the controller finds a nonzero a_j?

PE (i mod N). The controller broadcasts a_j with its index j to all PEs; each PE multiplies it by the nonzero weights in its slice of column j and accumulates into its own b_i. Zero activations are never broadcast, so their columns are skipped.

Recall

Which layers did EIE accelerate, and which did it not?

Fully connected layers of AlexNet and VGG-16 and the LSTM matrices of NeuralTalk, all matrix-vector products at batch size 1. It does not run convolutions.

Recap

If you remember nothing else

  • Pruning alone leaves gains on paper: a 91 percent sparse AlexNet FC6 runs only 2.5x faster on a CPU and 4x on a Titan X at batch 1, and slower than dense at batch 64.
  • Han's paradigm: train, compress (prune, quantize, Huffman), then run on an engine that computes directly on the compressed form (NeurIPS 2015, ICLR 2016, ISCA 2016, FPGA 2017).
  • EIE was the first accelerator for sparse, compressed networks: 189x faster and 24,000x more energy efficient than a CPU, 13x and 3,400x versus a GPU, 102 GOPS on compressed work equal to 3 TOPS dense, 64 PEs at 800 MHz, 600 mW.
  • Three savings: sparse weights (90 percent static) 10x compute and 5x memory; sparse activations (70 percent dynamic) 3x compute; weight sharing (4-bit) 8x memory. Rules of thumb 0 x A = 0 and W x 0 = 0.
  • Static sparsity is fixed after training; dynamic sparsity is created by ReLU per input and must be detected at run time.
  • Rows are interleaved, PE_k holds rows i with i mod N = k, so every output stays local; nonzero activations are broadcast with their index and zero activations skip whole columns.
  • EIE targets matrix-vector products in FC and LSTM layers at batch size 1, not convolutions.

Sources