cudatraining · lab notes

LESSON 02 · 2026.04.18 · T4

The true cost of copies — pageable vs pinned

Same kernel, same GPU. I only changed the host-side memory choice and end-to-end time jumped 5.6×. D2H alone jumped 12.7×. We break down the source of that gap with numbers and the page table.

GPU · T4 · sm_75 sweep · 16 runs PCIe Gen3 x16 effective · ~13 GB/s

Experiment

I added --pinned / --pageable flags to src/vector_add.cu and branched host-buffer allocation between cudaMallocHost and new float[]. Same GPU path — identical kernel, only host memory changes.

Transfer bandwidth plateau

pinnedpageableratio
H2D~12.3 GB/s~4.6 GB/s2.7×
D2H~13.1 GB/s~1.03 GB/s12.7×

End-to-end total time

npinnedpageableratio
2²⁰1.12 ms6.84 ms6.1×
2²²4.28 ms24.09 ms5.6×
2²⁴16.87 ms95.03 ms5.6×
2²⁶67.38 ms375.69 ms5.6×
2²⁸270.56 ms1519.26 ms5.6×

Kernel time is identical in both modes. The gap is 100% on the host-side copy.

Why only D2H is 12.7× — page faults

H2D reads pages the user already touched during init. No fault. Hence 2.7×.

D2H is the opposite. new float[n] only allocates virtual addresses without committing physical pages. When the driver CPU-memcpys from staging → pageable, every page incurs a demand-zero fault. A 1 GB buffer means roughly 262k page faults.

Even when pageable is unavoidable, pre-touch your output buffer. A single memset makes D2H several times faster.

T4 with pinned memory hits PCIe Gen3's effective ceiling

H2D 12.3, D2H 13.1 GB/s. Gen3 x16 theoretical 16 GB/s, effective ~13 GB/s. There's nothing more to squeeze. The three remaining levers are:

This is the background for why vLLM pins its KV cache on the GPU and why operator fusion pays off so well.

Small n is a different world

For n ≤ 2¹⁸, the kernel gets pinned against the launch-overhead floor (~4–7 µs). The "bandwidth %" concept loses meaning. At n = 2¹⁸, apparent bandwidth is 140% of theoretical — a spurious number coming from L2 cache hits. The crossover into true HBM-bound territory sits around n ≈ 2²⁰ (4 MB).

Structural one-liner

For memory-bound workloads the biggest lever isn't the kernel, it's the data path. Your kernel can sit at 70% of theoretical bandwidth and end-to-end still runs 5× slower if the host side is pageable.