Seyed Masoud Hosseini · Overview · Study log · Weekly summaries · Ideas · Search · Transcript · RSS feed

Parallel Computing & CUDA · Lecture 10 of 19 · 1:20:26

Lecture 10: Efficiently Evaluating DNNs on GPUs

Stanford CS149 I Parallel Computing I 2023 I Lecture 10 - Efficiently Evaluating DNNs on GPUs on YouTube

Study guide

What this lecture covers

This lecture asks how modern GPUs and CPUs run deep neural networks efficiently. It starts from a single neuron - a dot product followed by a nonlinearity - and builds up to full convolutional layers and Transformer attention blocks, showing at each step how the computation maps onto hardware that is good at dense matrix multiplication.

The lecture sits after the course's core parallel programming material and feeds directly into assignment four. After watching, you should be able to explain why convolution is implemented as matrix multiplication, why blocking a matrix multiply for cache reuse matters, why fusing operations like bias-add and max-pool saves memory traffic, and why GPUs (with features like tensor cores) are well suited to this workload.

Key ideas

  • Neuron as dot product: a neuron computes a dot product between weights and inputs, then applies a nonlinear function such as max(x, 0).
  • Convolution as matrix multiply (im2col): copying overlapping input patches into a matrix turns a convolution into a matrix-matrix product, so any fast GEMM library can execute it.
  • Arithmetic intensity: naive matrix multiply reads far more data than the math it does per byte; blocking submatrices into cache raises the ratio of computation to memory traffic.
  • Cache/shared-memory blocking: choosing a block size that fits the cache (or, on a GPU, shared memory as an explicit scratchpad) is the key trick for turning a bandwidth-bound loop into a compute-bound one.
  • Implicit GEMM: rather than materializing the huge duplicated im2col matrix, compute the matrix indices on the fly and fetch values from the original tensor, avoiding the memory blow-up.
  • Layer fusion: chaining a convolution's output straight into bias-add and max-pool while it is still on-chip avoids repeated round-trips to memory, which otherwise dominate runtime.
  • FlashAttention: computing attention's softmax in chunks (using a running max and sum) lets an entire attention block be fused, cutting memory footprint from quadratic to block-sized and enabling much longer sequences.
  • Tensor cores: a GPU instruction that performs a small fixed-size matrix multiply amortizes instruction overhead across many math operations, delivering an order of magnitude more throughput than scalar multiply-add.

Walkthrough

The deep-network workload (6:09)

The lecture opens by explaining why it appears here: it is useful preparation for assignment four. It frames a neuron as a dot product between a weight vector and an input vector, passed through a nonlinearity (here, a max with zero). Stacking neurons into layers produces either fully connected layers, where every output of one layer feeds every neuron of the next, or convolutional layers, where each output depends on a small sliding window of inputs.

Convolution as image processing and as matrix multiplication (12:16)

A concrete convolution example shows how different fixed weights average pixels (blurring) or compute finite differences (edge detection). The lecture then generalizes to filters with many input and output channels, arranged as tensors, and shows how a naive implementation needs seven nested loops. It walks through the classic trick of copying overlapping input patches into a wide matrix (im2col) so the convolution becomes a plain matrix-matrix product against a matrix of filter weights - letting any fast matrix multiply library do the work.

Why algorithm design matters first (18:23)

Before optimizing execution, the lecture lists three ways to make deep networks faster: better network architectures (fewer FLOPs for the same accuracy, as seen across years of ImageNet models), mapping a fixed architecture well onto hardware, and specialized accelerator hardware. It shows how architectural changes alone produced roughly a 25x reduction in weights and computation over a few years - much faster than hardware improved in the same period.

Blocking matrix multiply for cache reuse (34:39)

Using plain three-loop matrix multiplication as an example, the lecture shows that naive execution is bandwidth-bound: for n-cubed work you only touch n-squared data, but a straightforward implementation still reads two values per multiply-add. The fix is to block the computation into submatrices sized to fit in cache (or, on a GPU, explicitly copied into shared memory as a scratchpad), raising arithmetic intensity from roughly constant to proportional to the block size. Multiple levels of blocking (L1, L2, L3, even registers) compound this benefit.

Implicit GEMM and layer fusion (48:59)

Turning a convolution into an explicit im2col matrix wastes enormous memory, since each input pixel gets duplicated many times. The lecture introduces implicit GEMM, where the same loop structure is used but the matrix indices are computed on the fly and values are fetched directly from the original tensor, avoiding that duplication. It also covers operator fusion: rather than writing a convolution's output to memory and reading it back for bias-add and max-pool, doing all three while the data is still in cache or shared memory removes several bandwidth-bound round trips - explaining why libraries like cuDNN expose fused kernels and why compilers such as Jax and Triton try to automate this fusion.

FlashAttention: fusing through softmax (1:04:13)

Attention layers compute an outer product of query and key vectors into an n-by-n matrix, apply softmax row by row, then multiply by a value matrix. Softmax appears to require the whole row before it can scale anything, which normally forces the huge intermediate matrix through memory multiple times. The lecture shows how softmax can be computed incrementally in blocks using a running maximum and sum, enabling the whole attention computation to be fused block by block. This shrinks memory use from quadratic in sequence length to block-sized, which is credited with enabling much longer context windows in large language models.

Why GPUs suit this workload (1:14:18)

The lecture closes by connecting the workload's properties - abundant parallelism, high potential arithmetic intensity, and heavy use of SIMD-style operations - to why GPUs are a good fit. It also explains tensor cores as instructions that perform small fixed-size matrix multiplies, amortizing per-instruction overhead across many math operations and delivering roughly an order of magnitude more throughput than doing the same work with scalar multiply-adds.

Before you watch

  • Be comfortable with dependency graphs, SIMD, and arithmetic intensity/bandwidth-bound reasoning from earlier lectures in this course.
  • Basic familiarity with what a convolution and a matrix multiplication are will help; the lecture defines both from scratch but moves quickly.
  • Recall the blocked, bandwidth-bound examples from earlier assignments, since this lecture reuses that reasoning for matrix multiply.

Check your understanding

  1. Why does expressing a convolution as an im2col matrix multiplication create a much larger memory footprint than the original input, and how does implicit GEMM avoid that?
  2. Explain why the naive three-loop matrix multiplication is bandwidth-bound even though it does n-cubed work on n-squared data.
  3. How does blocking the matrix multiplication change its arithmetic intensity, and what determines the largest block size you can choose?
  4. Why does fusing bias-add and max-pool into the same pass as a convolution improve performance?
  5. What property of softmax made it seem impossible to fuse through an attention block, and how does the chunked computation get around it?

Vocabulary

deep neural network (DNN) (noun)
A neural network made of many stacked layers of neurons.
The lecture explains how to evaluate a deep neural network efficiently on a GPU.
dot product (noun)
A calculation that multiplies matching elements of two vectors and adds up the results.
A neuron computes a dot product between weights and inputs.
nonlinearity (noun)
A function applied after a linear calculation that lets networks learn complex patterns.
The neuron applies a nonlinearity like max(x, 0) after the dot product.
fully connected layer (noun)
A layer where every input connects to every neuron in the next layer.
A fully connected layer has no sliding-window restriction.
convolutional layer (noun)
A layer where each output depends only on a small local window of inputs.
A convolutional layer processes small patches of the image at a time.
channel (noun)
One of several parallel feature planes stored at each position of a tensor.
A filter can combine information across many input channels.
im2col (noun)
A technique that rearranges overlapping input patches into a matrix so convolution becomes matrix multiplication.
im2col turns the convolution into a plain matrix-matrix product.
GEMM (general matrix multiply) (noun)
A standard, highly optimized routine for multiplying two matrices.
Any fast GEMM library can execute the reshaped convolution.
FLOP (floating-point operation) (noun)
A single basic math operation performed on a decimal number.
Better architectures reduce the number of FLOPs needed for the same accuracy.
cache reuse (noun)
Using data already stored in the cache multiple times instead of reloading it.
Blocking the matrix multiply improves cache reuse.
scratchpad (noun)
A small, fast memory area explicitly managed by the program instead of automatic caching.
GPU shared memory works as an explicit scratchpad.
implicit GEMM (noun)
A method that computes matrix multiply indices on the fly instead of building the full duplicated matrix first.
Implicit GEMM avoids the memory blow-up of a full im2col matrix.
operator fusion (noun)
Combining several operations into one pass to avoid repeated memory access.
Operator fusion chains convolution, bias-add, and max-pool together.
round trip (noun)
A full journey of data going out to memory and coming back.
Fusion avoids extra round trips to memory between operations.
softmax (noun)
A function that turns a row of numbers into probabilities that add up to one.
Attention applies softmax to each row of scores.
quadratic (adjective)
Growing in proportion to the square of the input size.
Attention's memory use is normally quadratic in sequence length.
running maximum (noun)
A value kept updated to be the largest number seen so far.
FlashAttention tracks a running maximum while processing chunks.
tensor core (noun)
A specialized GPU unit designed to perform small matrix multiplications very fast.
Tensor cores deliver much higher throughput than scalar multiply-add.
throughput (noun)
The total amount of work completed per unit of time.
Tensor cores give an order of magnitude more throughput.
accelerator (noun)
Specialized hardware built to speed up a specific type of computation.
Specialized accelerator hardware is one way to make deep networks faster.

From the YouTube description

Efficiently scheduling DNN layers, mapping convs to matrix-multiplication, transformers, layer fusion

To follow along with the course, visit the course website:
https://gfxcourses.stanford.edu/cs149/fall23/

Kayvon Fatahalian
Associate Professor of Computer Science, Stanford University
https://graphics.stanford.edu/~kayvonf/

Kunle Olukotun
Cadence Design Systems Professor, Professor of Electrical Engineering and of Computer Science, Stanford University
https://engineering.stanford.edu/people/oyekunle-olukotun

Learn more about the online course and how to enroll: https://online.stanford.edu/courses/cs149-parallel-computing

To view all online courses and programs offered by Stanford, visit: https://online.stanford.edu/

← Lecture 9: Distributed Data-Parallel Computing Using Spark · Lecture 11: Cache Coherence →