Lab 01 — PTX/SASS Dissection

Phase: 03 — GPU Compilers | Difficulty: ⭐⭐⭐☆☆ | Time: 3–4 hours Tools: CUDA toolkit (nvcc, cuobjdump) — or godbolt.org with zero install

Concept primer: ../WARMUP.md Ch. 3–8.

Run

nvcc -ptx -o saxpy.ptx kernels.cu                  # PTX for annotation
nvcc -cubin -arch=sm_80 -o kernels.cubin kernels.cu
cuobjdump --dump-sass kernels.cubin > kernels.sass # SASS for the hunt
nvcc -Xptxas=-v -c kernels.cu                      # registers/smem/spills

No toolkit? godbolt.org → language CUDA C++ → compiler "NVCC (latest)" → flags -O3 -arch=sm_80; the right pane shows PTX, and "Add new → Device" shows SASS. Everything below except the fatbin step works there.


0. The mission

Four tiny kernels (kernels.cu), four investigations:

  1. saxpy — annotate every PTX line. Template in saxpy-annotation-template.md; answer key in saxpy-annotated.md. Do not peek early.
  2. guarded — a small if body: find where the branch disappeared in SASS (if-conversion → @%p-predicated stores / SEL).
  3. unrolled#pragma unroll 8 loop: count the replicated bodies in SASS; note the register count change in -Xptxas=-v.
  4. spiller — a kernel with a large per-thread array. Compile normally, then with -maxrregcount=16: find the LDL/STL local-memory spills that appear, and the "bytes spill stores/loads" line in ptxas output.

Then the fatbin dissection:

nvcc -gencode arch=compute_80,code=sm_80 \
     -gencode arch=compute_90,code=sm_90 \
     -gencode arch=compute_90,code=compute_90 -c kernels.cu -o fat.o
cuobjdump --list-elf fat.o     # two ELFs (sm_80, sm_90)...
cuobjdump --dump-ptx fat.o | head   # ...plus embedded PTX (compute_90)

Map each artifact to the load-time decision tree (WARMUP Ch. 7) and write, in two sentences, what happens on (a) an A100, (b) an H100, (c) whatever ships next.

1. The annotation rubric (what "done" means for saxpy)

Your annotation must identify: the .param ABI and ld.param prologue; the cvta.to.global state-space conversion and why it exists; the mad.lo.s32 index formula and which special registers feed it; the setp+@%p bra tail guard; the mul.wide.s32 byte-offset computation; the fma.rn.f32 contraction (and what -fmad=false would do to it). Six items — the same six the WARMUP Ch. 5 tour narrates.

2. Findings sheet (fill in)

KernelFlag setupWhat I found (instruction + line)Mechanism (one sentence)
guarded-O3
unrolled-O3
spillerdefault
spiller-maxrregcount=16
fat.o3 gencodes

3. Extensions

  • Cross-compiler: same saxpy through clang -x cuda --cuda-device-only -S (LLVM NVPTX) — diff the PTX against nvcc's. What's identical (the ABI), what differs (instruction selection, virtual register naming)?
  • Cross-vendor: on Godbolt, compile the HIP version with hipcc for gfx90a and skim the GCN ISA — note there's no PTX-like layer (WARMUP Ch. 9's asymmetry, seen with your own eyes).
  • Tensor Core spotting: compile a 16×16 wmma example and find HMMA in SASS — the instruction the whole AI economy runs on.

4. What this lab proves about you

The compiler stack is no longer folklore: you've read the contract layer (PTX), the truth layer (SASS), and the deployment layer (fatbin) with your own eyes, and you can connect each to a production decision (numerical policy, occupancy tuning, build matrix).