interviewpath
  • 0day streak
  • 10total XP
  • Level 1
0/6

Unit 8 · AI infrastructure · Lesson 5 of 10

Input pipelines, host-device transfer and overlap

A GPU is only as busy as the data and communication feeding it. Input pipelines, host-to-device copies and collectives must overlap with compute or the most expensive component waits; this is a frequent root cause behind "training is slower than expected", and it is diagnosed with measurements, not guesses.
About 3 hFocus mode

Step 1: Learn the ideas

  • Pipeline view: storage, decode or tokenize, batch, host memory, device, compute, communication
  • DataLoader workers, prefetching and persistent workers
  • Collation, padding, length bucketing and sequence packing
  • Pageable versus pinned memory and non-blocking copies
  • CUDA streams, events and synchronization points
  • Overlapping gradient all-reduce with backward and parameter all-gather with compute
  • Sharded storage formats and streaming datasets
  • Shuffle buffers, determinism and resumable state
  • Reading timelines for exposed data and communication time

Why it matters

Accelerators do useful work only while data and communication keep up with them. When input loading, host-to-device copies or collectives are not overlapped with compute, the most expensive component waits. "Training is slower than expected" is often an input-pipeline or synchronization problem, and interviewers want to see a measured diagnosis rather than a list of tricks.

Core ideas

A pipeline view. Training is a chain: storage, decode and augment (or tokenize and pack), batch, host memory, device, compute, communication. The slowest stage sets throughput; buffers and prefetching hide variability but cannot fix a producer that is slower on average. The quickest test is to replace the dataset with synthetic tensors already on the GPU: if the step gets much faster, you are input-bound.

DataLoader mechanics. Worker processes load and transform samples in parallel, outside the main Python thread. Each worker prefetches a few batches; persistent workers avoid restarting processes every epoch. More workers help until CPU cores, host memory or storage bandwidth saturate, and each worker holds its own copy of dataset state, which can inflate host memory. For sequences, padding to the longest item in a batch wastes compute; bucketing by length or packing several sequences into one row reduces the waste.

Pinned memory and copies. The GPU's copy engines read host memory directly only when it is page-locked (pinned); a copy from ordinary pageable memory first passes through a pinned staging buffer. With non_blocking=True the host thread does not wait for the copy, but the copy overlaps with kernels on the GPU only if the source is pinned, the copy runs on a non-default stream and a copy engine is free. Pinning a tensor right before copying it adds work and can be slower than a plain copy; the benefit comes from producing batches directly in pinned memory (DataLoader pin_memory=True pins in a background thread) or reusing pinned buffers. Non-blocking device-to-host copies need an explicit synchronization before the CPU reads the result, or it may read incomplete data.

Streams and synchronization. Kernels on one stream run in order; work on different streams may overlap. Hidden synchronization points serialize the pipeline: .item(), .cpu(), printing tensor values, operations whose output shape depends on data (nonzero, boolean masking) and explicit synchronize calls. Logging the loss value every step is a classic stall.

Communication overlap. DDP launches bucketed gradient all-reduces during backward; FSDP prefetches the next layer's parameter all-gather. Overlap helps only when enough independent compute exists to cover the transfer and when communication and compute do not compete for the same resources.

What to look for in a timeline. GPU idle gaps at the start of each step (waiting for data), host-to-device copy durations, CPU time inside the DataLoader's next call, and collectives not covered by compute.

Common misconceptions

  • "More DataLoader workers are always faster." Beyond the available cores, memory and I/O bandwidth, workers contend and startup cost grows.
  • "non_blocking=True makes every copy asynchronous and overlapped." It frees the host thread; overlap with kernels needs pinned memory and a separate stream, and unsynchronized device-to-host results can be wrong.
  • "High GPU utilization means the input pipeline is fine." Utilization counts any running kernel; compare step time with a synthetic-data baseline.
  • "Overlap happens automatically." It needs independent work, separate streams and no synchronization points in between.
  • "Data loading only matters for images." Tokenization, packing, decompression and remote object storage bottleneck text pipelines too.

How to approach it

Profile first, then change one thing at a time: workers, pinned memory, batch layout, synchronization points, communication overlap. In interviews, describe the synthetic-data test, the timeline signals you would look for, and the fix for each signal. Senior discussions add dataset sharding across many hosts, deterministic shuffling with resumable state, and storage throughput planning.

Suggested order

  1. 1Read the single- and multi-process loading and memory-pinning sections of the PyTorch torch.utils.data documentation.
  2. 2Read the PyTorch guide on non_blocking and pin_memory() and reproduce one of its timing comparisons.
  3. 3Read the asynchronous execution and CUDA streams sections of PyTorch CUDA semantics.
  4. 4Read the CUDA Best Practices sections on pinned memory and on overlapping transfers with computation.
  5. 5Do the profile-a-training-step project, confirm or rule out an input bottleneck with the synthetic-data test, and inspect the timeline in Nsight Systems if available.

Step 2: Check off what you can do

Tap each one you can genuinely do or explain. Each earns 10 XP.

Step 3: Go deeper

  • PyTorch: torch.utils.data (Dataset and DataLoader)Start here

    PyTorch documentation

    Section: Single- and Multi-process Data Loading

    How workers, batching, collation and memory pinning behave in the standard data-loading API.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • A guide on good usage of non_blocking and pin_memory() in PyTorchStart here

    PyTorch tutorials

    When pinned memory and non-blocking copies help, when they cost more than they save, and the device-to-host synchronization pitfall.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • PyTorch: CUDA semantics

    PyTorch documentation

    Section: CUDA streams

    Stream ordering, synchronization rules and asynchronous execution as PyTorch implements them.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • CUDA C++ Best Practices Guide

    NVIDIA Documentation

    Section: Asynchronous and Overlapping Transfers with Computation

    The hardware view of copy-compute overlap and pinned memory.

    Open(opens in a new tab)Link responded, 5 Oct 2026
  • NVIDIA Nsight Systems User Guide

    NVIDIA Documentation

    System-wide timelines that show data waits, copies, kernels and communication together.

    Open(opens in a new tab)Link responded, 5 Oct 2026

Step 4: Practice

Take a training script you know, record a baseline step time, then run with synthetic on-device data to bound the possible gain. Profile, label the timeline, and change one setting at a time (workers, pin_memory, removing per-step .item() calls, length bucketing), recording step time and GPU idle time after each change. The table of changes and effects is the evidence you will cite in an interview.

Record attempts on each problem’s page (+15 XP, +10 more when solved on your own).

Step 5: Test yourself

Answer each one out loud or on paper before you finish the lesson.

  1. Question 1What does the synthetic-data test tell you, and what can it miss?
  2. Question 2Which conditions must hold for a host-to-device copy to overlap with a kernel?
  3. Question 3Name four operations that force host-device synchronization.
  4. Question 4How do length bucketing and sequence packing change wasted compute?
  5. Question 5Why can adding DataLoader workers make a job slower?

You’re done when you can

  • Determine whether a training script is input-bound using a synthetic-data comparison and a profiler timeline.
  • Explain when pinned memory and non-blocking copies help, when they do not, and the device-to-host synchronization pitfall.
  • Remove at least one hidden synchronization point from a training loop and show its effect in a trace.
  • Describe how DDP overlaps gradient communication with backward and what limits that overlap.

Finish the lesson

How confident do you feel?

Lesson complete!

+50 XP

Reviews will come up on the Practice tab so it sticks.

Your notes and study time

Log study time