Lesson 10 · Arc finale

GPU Architecture · Execution & Operations

Seeing inside: observability & debugging

What metadata travels with your kernel, and exactly which data source each tool reads — so a symptom points you at the right instrument.

This is where the arc pays off. You know how a launch runs (L7), how data, completion, and errors flow (L8), and how the GPU is shared (L9). When something is wrong or slow, you reach for a tool — but the tools aren't interchangeable, because they watch the GPU through different windows. Some read cheap driver counters, some trace events on a timeline, some read expensive hardware performance counters, some instrument your binary. Knowing which data source a tool uses is what tells you when to reach for it.

The one win

Match the question to the instrument: "is it even using the GPU?" is a driver-counter question (nvidia-smi); "where does wall-clock go?" is a tracing question (Nsight Systems); "why is this kernel slow?" is a hardware-counter question (Nsight Compute); "is it wrong?" is an instrumentation question (compute-sanitizer). Different windows, different data.

First: what metadata travels in your binary

A tool can only show you source lines if you compiled the mapping in. Two flags, and the difference matters:1

-lineinfo — for profiling

-G — for debugging

Mechanically: a profiler samples a program-counter (a SASS instruction address), looks it up in the cubin's .debug_line table to recover file+line, and aggregates its counters per source line. No line info compiled in → the source column is blank and you're reading raw SASS and mangled names. A release build strips these sections, which is why a stripped binary profiles as addresses only.1

The performance tools: a zoom ladder

The three performance tools form a ladder — each narrower in scope, deeper in detail, and costlier to run than the last. You walk down it: start cheap and wide, descend only as far as the question demands.

whole GPU · live

nvidia-smi

Is it used? Memory, power, temp, clocks, throttling, which processes.

whole app · timeline

Nsight Systems

Where does wall-clock go? Gaps, poor overlap, CPU-bound stretches, tiny kernels.

one kernel · deep

Nsight Compute

Why is this kernel slow? Occupancy, memory vs compute bound, warp stalls.

What separates them is entirely their data source:

ToolWhat it showsData sourceCost
nvidia-smi
/ NVML
Utilization, memory, power, clocks, temp, throttle reasons, processes. Driver counters & on-chip sensors ~free, live
Nsight
Systems
Unified CPU+GPU timeline: API calls, kernels, memcpies, overlap, gaps; a launch linked to its kernel. Tracing via CUPTI (event records + timestamps + correlation IDs) low
Nsight
Compute
Per-kernel depth: achieved occupancy, memory throughput vs peak (roofline), warp stall reasons, cache/sector efficiency. Hardware performance counters + PC/warp-state sampling high

Three details worth carrying:

Warp stall reasons — the arc coming full circle

Nsight Compute's most illuminating output samples the warp program counter to report why warps were idle — the very stall reasons from Lesson 2. stall_long_scoreboard = waiting on global/local memory (the bandwidth wall of Lesson 4); stall_barrier = waiting at a __syncthreads() (Lesson 6); stall_short_scoreboard = shared-memory/MIO latency. This is where every physical lesson becomes a number you can read off your own kernel.5

The correctness tools: a different axis

Slow and wrong are different questions, and the counters above won't catch wrong. Two tools work by different means entirely:

On your box

All of these run in your WSL2 setup. Two practical notes: build with -lineinfo whenever you profile so Nsight can point at source lines; and Nsight Compute's hardware counters require performance-counter access — if ncu reports ERR_NVGPUCTRPERM, that's a permissions gate to enable, not a broken install. compute-sanitizer and nvidia-smi need no special setup.

The troubleshooting table

The whole lesson, compressed to "symptom → reach for → because of the data it reads":

SymptomReach forBecause it reads…
Is the GPU even used? OOM? throttling?nvidia-smidriver counters & sensors
GPU shows 100% but it's slow→ Nsight Computereal occupancy (HW counters), not time-busy
Where's wall-clock going? bad overlap, tiny kernels, CPU-bound?Nsight SystemsCUPTI trace + correlation IDs
This one kernel is slow — memory- or compute-bound?Nsight ComputeHW counters (roofline)
Why are warps idle?Nsight ComputePC / warp-state sampling (stall reasons)
Wrong results / crash — bad pointer, race, uninit, bad sync?compute-sanitizerbinary instrumentation
Step through device code, inspect a lane's registerscuda-gdb (-G)debugger back-end + DWARF
Crash surfaced on an innocent later call (L8 sticky error)compute-sanitizerinstrumentation pins the real kernel + address

That's the whole decision tree. For the full ecosystem — every tool in the course plus the ones we didn't reach (nsys/ncu siblings, CUPTI, NVTX, DCGM, the monitors, and current-vs-deprecated status), each with its data source and best article — see the companion CUDA Tools & Further Reading card.

Check yourself

From memory — one click locks each answer.

Data sourcenvidia-smi reports your GPU at 100% utilization, yet the program is slow. This is because GPU-Util —

Tool choiceYour app spends most of its wall-clock time somewhere, but no single kernel looks slow. You reach for —

MechanismNsight Compute re-runs your kernel several times because —

Primary source (≈20 min)

Nsight Compute — Kernel Profiling Guide (kernel replay, hardware counters, warp-state sampling, roofline): read it here. Then skim the CUPTI overview (Activity/Callback APIs, correlation IDs) to see what Nsight Systems is built on: docs.nvidia.com/cupti.

That closes the execution & operations arc — and the tools in this lesson are exactly the ones the optimization arc will put in your hands. Next, the payoff we've been building toward since Lesson 6: a real tiled matmul kernel — load a tile into shared memory once, reuse it many times — measured against your 320 GB/s, then profiled under Nsight Compute so you read stall_long_scoreboard dropping on your own code as the tiling takes hold. Every lesson so far becomes a number you can move. Say the word when you're ready to build it.

Notes & citations

  1. CUDA Compiler Driver NVCC — --generate-line-info (-lineinfo): "Generate line-number information for device code" (optimizations intact; for profiling). --device-debug (-G): generates device debug info and, without --dopt, "turns off all optimizations… not intended for profiling." CUDA Binary Utilities — cubins are ELF with DWARF .debug_* sections; .debug_line maps address → source line. nvcc guide · binary utilities
  2. CUPTI Overview — the Activity API "asynchronously records CUDA activities" (kernels, memcpy) with GPU timestamps; the Callback API notifies on API enter/exit; the PC Sampling API samples "the warp program counter and warp scheduler state (stall reasons)." docs.nvidia.com/cupti
  3. NVML utilization semantics — nvmlUtilization_t.gpu is the "percent of time over the past sample period during which one or more kernels was executing." Time-busy, not saturation: a kernel on one SM reports 100%. (Use SM-activity/occupancy metrics for true utilization.) NVML API
  4. CUPTI Activity API — each API activity record carries a correlationId that "matches the correlation ID of the associated kernel, memcpy, or memset activity record that the API call initiated"; kernel records carry GPU-timestamp start/end. This is how Nsight Systems links the host launch to the GPU kernel. CUPTI Activity API
  5. Nsight Compute — Kernel Profiling Guide. "The number of metrics originating from hardware performance counters that the GPU can collect at the same time is limited," so the kernel is replayed once per pass; memory written by the kernel is saved and restored between passes; launches are serialized and caches flushed for determinism. Warp Stall Sampling reports stall reasons (Long/Short Scoreboard, Barrier, Wait, …). docs.nvidia.com/nsight-compute
  6. Compute Sanitizer manual — memcheck (out-of-bounds/misaligned), racecheck (shared-memory races), initcheck (uninitialized global reads), synccheck (invalid synchronization); runtime binary instrumentation; replaces the deprecated cuda-memcheck. docs.nvidia.com/compute-sanitizer
  7. CUDA-GDB manual — source-level device debugging; breakpoints in kernels; cuda device sm warp lane block thread focus; info cuda warps/lanes; full source-level debugging needs a -G build. docs.nvidia.com/cuda/cuda-gdb
← Lesson 9 ⌂ Home Lesson 11 →