skip to content
Arnur Yembergen
← writings
note

A minimal nsys recipe for CUDA kernels

· 1 min

nsys profile with default flags records everything and answers nothing. For kernel work I keep coming back to the same invocation:

nsys profile \
--trace=cuda,nvtx \
--sample=none --cpuctxsw=none \
--capture-range=cudaProfilerApi --capture-range-end=stop \
-o run1 ./bench

--sample=none --cpuctxsw=none drops the CPU sampling that bloats traces and skews timing. --capture-range=cudaProfilerApi makes nsys wait for cudaProfilerStart() in the binary, so warmup iterations never enter the trace. The kernel table comes out without a GUI round-trip:

nsys stats --report cuda_gpu_kern_sum run1.nsys-rep

Before reading anything into a kernel time, do the bandwidth arithmetic. A memory-bound kernel that reads BrB_r bytes and writes BwB_w bytes in time tt achieves

BWeff=Br+Bwt\mathrm{BW}_{\text{eff}} = \frac{B_r + B_w}{t}

A copy of 2282^{28} fp32 elements moves 2 GiB; at 2.1 ms that is about 1.0 TB/s, two thirds of an A100 40 GB’s 1.56 TB/s, so there is real headroom left. If the number already sits near peak, the kernel is done. Stop staring at SASS.