Model Training Infrastructure and Distributed Training Questions
Scaling model training across hardware and time. Covers GPU/accelerator considerations, data and model parallelism, distributed and large-scale training, experiment tracking and training infrastructure, and the training-versus-inference compute tradeoff. Focuses on the systems and resource decisions that make large-model training feasible.
Explain the GPU memory hierarchy and how it impacts training neural networks. Cover HBM (GPU DRAM), L1/L2 caches, shared memory, and host (CPU) memory. For a training workload, describe where model parameters, activations, optimizer state, and data batches should typically reside. Explain transfer costs and latency differences between PCIe and NVLink and give practical rules of thumb for minimizing data movement between host and devices in production training pipelines.
Sample Answer
Direct answer
A GPU's memory hierarchy has several tiers with very different capacity and bandwidth trade-offs, from large-but-slower host (CPU) memory, through the GPU's own high-bandwidth DRAM (HBM), down to small-but-extremely-fast on-chip caches and shared memory close to the compute units; efficient training keeps data as close to the compute units as possible for anything accessed repeatedly, since moving data down this hierarchy costs bandwidth and latency at every level.
Structured elaboration
- Host (CPU) memory: the largest tier (often hundreds of GB to TB), but connected to the GPU only via PCIe (or NVLink, if available), meaningfully slower and higher-latency to access than the GPU's own memory; used for staging data before transfer, or for offloaded optimizer state/parameters in memory-constrained training. Data batches typically originate here (loaded and preprocessed on the CPU) before being transferred to the GPU for consumption, which is exactly the host-to-device transfer whose cost is analyzed below.
- HBM (GPU DRAM): the GPU's own dedicated high-bandwidth memory (tens to over a hundred GB on modern data-center GPUs), where model weights, gradients, optimizer state, and activations live during training; much faster than host memory but still an order of magnitude or more slower than the on-chip caches below it.
- L2 cache: a chip-wide cache shared across the GPU's compute units, smaller than HBM (tens of MB) but faster, automatically caching recently-accessed HBM data to reduce redundant HBM round-trips.
- L1 cache / shared memory: per-compute-unit (per streaming multiprocessor), very small (tens to low hundreds of KB) but extremely fast, used explicitly by well-optimized kernels to hold data being actively reused within a tight computational loop (e.g. matrix-multiplication tiling keeps a working tile in shared memory rather than re-reading from HBM for every operation on it).
- Where each quantity should reside: model parameters, gradients, and optimizer state persist in HBM for the full duration of training (they're read/written every step and are far too latency-sensitive to page in from host memory on the hot path); activations persist in HBM only for as long as needed (through the forward pass and until consumed by the corresponding backward pass, which is exactly what activation checkpointing and offloading techniques manage more aggressively when HBM is the binding constraint); data batches originate in host memory (where the CPU data-loading pipeline produces them) and are transferred to HBM just-in-time, one prefetched batch ahead of when the GPU needs it, rather than staging the entire dataset in either host or GPU memory at once.
- PCIe versus NVLink transfer cost and latency: for host-to-device transfer specifically (as opposed to GPU-to-GPU transfer), the relevant link is PCIe in the overwhelming majority of systems, since host memory connects to the GPU over the PCIe bus regardless of whether the GPUs also have NVLink to each other; PCIe generation and lane count set the achievable host-to-device bandwidth (for example, PCIe 4.0 x16 tops out around 32GB/s, PCIe 5.0 x16 around 64GB/s), meaningfully lower than intra-node NVLink's GPU-to-GPU bandwidth, and every host-to-device transfer also pays a fixed per-transfer latency overhead (kernel launch and DMA setup cost) that matters disproportionately for many small transfers versus fewer, larger ones. NVLink does not change host-to-device transfer at all on typical systems (host memory is not NVLink-connected); NVLink's advantage is specific to GPU-to-GPU traffic, which is why minimizing host-device movement (below) is a PCIe-bandwidth problem specifically, distinct from the GPU-to-GPU NVLink-versus-PCIe question covered elsewhere in this topic.
- Practical rules of thumb for minimizing host-device data movement: (1) use pinned (page-locked) host memory for any tensor being transferred, since pinned memory supports faster, asynchronous DMA transfer than regular pageable memory; (2) issue the transfer asynchronously and overlap it with GPU compute on the previous batch (the same prefetching principle as the data-loading pipeline, applied specifically to the final host-to-device copy step) rather than blocking the GPU on each transfer; (3) batch small transfers into fewer, larger ones wherever possible, since each individual transfer pays fixed overhead independent of its size; (4) avoid unnecessary round-trips, such as pulling a GPU tensor back to host memory for logging/debugging on every step, which silently reintroduces PCIe-bound stalls into an otherwise GPU-resident training loop; and (5) keep anything reused across steps (model parameters, optimizer state) resident on the GPU permanently rather than re-transferring it, reserving host-device transfer specifically for the genuinely new data (the next batch) each step actually needs.
Impact on training: operations that are compute-bound (dense matrix multiplies, well-optimized to reuse data from fast on-chip memory) achieve close to the GPU's peak theoretical throughput; operations that are memory-bound (elementwise operations processing each value once, with little reuse) are limited by HBM bandwidth, not compute throughput, regardless of how fast the compute units themselves are, which is a large part of why operator fusion (combining several memory-bound operations into one kernel to reduce redundant HBM round-trips) is a meaningful optimization technique.
Worked example
A well-optimized matrix multiplication kernel tiles the computation so each tile of the input matrices is loaded into fast shared memory once and reused for many multiply-accumulate operations before being evicted, achieving high compute-unit utilization; a naive elementwise operation (like adding a bias vector) that reads and writes HBM directly for every element with no reuse is instead limited by HBM's bandwidth ceiling, explaining why such operations show comparatively low measured throughput relative to the GPU's advertised peak FLOPS, despite being computationally simple.
Trade-offs & pitfalls
A common misconception is assuming a GPU's advertised peak FLOPS figure represents achievable throughput for any workload; the memory hierarchy means actual achieved throughput depends heavily on how much data reuse a given operation allows, with memory-bound operations achieving only a fraction of peak FLOPS regardless of how fast the compute units theoretically are.
Design a federated learning architecture across multiple data-owner domains (e.g., banks) where raw data cannot leave each domain. Include secure aggregation, model update orchestration, handling non-iid data, model personalization, privacy guarantees, and governance for model promotion and validation.
Sample Answer
Direct answer
A federated learning architecture across data-owner domains that cannot share raw data trains a shared global model by having each domain train locally on its own data and share only model updates (not data) with a central aggregator, using secure aggregation to ensure even the aggregator cannot see any individual domain's raw update, only the combined result.
Structured elaboration
-
Federated averaging (the core training loop): the central server sends the current global model to each participating domain; each domain trains it locally for several steps on its own private data; each domain sends back only the resulting model update (weight delta), never the raw data; the server averages the updates (typically weighted by each domain's local dataset size) to produce the next global model, and the cycle repeats.
-
Secure aggregation: standard federated averaging still exposes each domain's individual update to the central server, which is itself a privacy leak risk (model updates can sometimes be reverse-engineered to reveal information about the underlying data); secure aggregation protocols (using cryptographic techniques like secret sharing or homomorphic encryption) let the server compute the SUM or average of all domains' updates without ever seeing any individual domain's update in the clear, only the aggregated result.
-
Handling non-IID data across domains: different domains (different banks, in this example) often have meaningfully different data distributions (different customer demographics, different transaction patterns), which can slow or destabilize federated averaging's convergence relative to training on pooled, IID data; mitigations include more sophisticated aggregation algorithms (weighting or clustering domains by similarity) or accepting somewhat slower convergence as an inherent cost of the privacy-preserving constraint.
-
Communication efficiency: since domains may have limited or intermittent connectivity (unlike a tightly-coupled data-center cluster), the federated protocol needs to tolerate domains dropping out of a given round and rejoining later, and often benefits from compressing the model updates communicated (similar in spirit to gradient compression techniques) to reduce bandwidth needs over what may be a much more constrained network than an internal data-center interconnect.
-
Model personalization: the shared global model produced by federated averaging is a compromise across all domains' data distributions, which, given the non-IID differences between domains noted above, may underperform a model specifically adapted to any single domain's own distribution; personalization addresses this by having each domain take the converged (or periodically-updated) global model and fine-tune it locally on its own data for a small number of additional steps before deployment, or by using a personalization-aware training scheme (e.g. keeping a subset of layers, often the final classification head, purely local/per-domain while only the shared feature-extraction layers are federated), giving each domain a model that benefits from the collective training signal while still being tailored to its own data characteristics.
-
Governance for model promotion and validation: since no single party has access to the full pooled dataset, validating a candidate global model before promoting it to production at every domain needs its own governance process: each domain validates the candidate model against its own held-out local data (never shared centrally) and reports only aggregate validation metrics (accuracy, calibration, or fairness metrics) back to a governance body, which then applies a pre-agreed promotion threshold (e.g. the model must not regress below a floor on any single domain's reported metrics, not just the cross-domain average) before the model is promoted from candidate to production status across all participating domains; this per-domain validation-without-data-sharing requirement is itself a direct consequence of the same raw-data-never-leaves-the-domain constraint that shapes the rest of the architecture.
Worked example
Five banks jointly training a fraud-detection model: each round, the central coordinator distributes the current global model to all five banks; each bank trains it locally for, say, 5 epochs on its own transaction data (which never leaves that bank's infrastructure); each bank submits its model update through a secure-aggregation protocol that combines all five updates into one averaged update without the coordinator (or any bank) ever seeing another bank's individual update; the coordinator applies this combined update to produce the next round's global model, repeating until convergence.
Trade-offs & pitfalls
Federated learning's privacy guarantee has real limits worth being explicit about: while raw data and individual updates are protected, the aggregated global model itself can, in principle, still leak some statistical information about the collective training data (a general risk with any trained model, not specific to federation), and organizations with genuinely strict requirements sometimes layer differential privacy (adding calibrated noise to updates) on top of secure aggregation for a stronger, quantifiable privacy guarantee, at some further cost to model quality.
You need to implement a custom fused transformer-attention kernel to leverage Tensor Cores for better throughput. Explain design choices and implementation steps either using CUDA WMMA APIs or Triton: data layout, tile sizes, alignment constraints, memory staging (shared memory), avoiding bank conflicts, and validation for numerical correctness and performance regression testing.
Sample Answer
Direct answer
Implementing a custom fused transformer-attention kernel to leverage Tensor Cores means combining several steps of the attention computation (the QK^T matrix multiply, the softmax, and the subsequent multiply by V) into a single GPU kernel that keeps intermediate results in fast on-chip memory rather than round-tripping through HBM between each step, while structuring the matrix multiplications specifically to match Tensor Cores' preferred tile sizes and precision.
Structured elaboration
- Why fusion matters here specifically: a naive, unfused attention implementation computes QK^T (writing the full attention score matrix to HBM), then reads it back for softmax (writing the result back to HBM again), then reads it back again for the final multiply by V; for long sequences, this attention-score matrix is large (quadratic in sequence length) and this round-tripping is a substantial, avoidable HBM bandwidth cost. Fusing these steps into one kernel (as FlashAttention-style implementations do) keeps intermediate results in fast shared memory/registers, computing the whole attention operation for a tile of the sequence without ever materializing the full attention-score matrix in HBM.
- Tiling for Tensor Cores: the QK^T and attention-weights-times-V matrix multiplications need to be structured as tiled operations matching Tensor Cores' preferred small-matrix-tile granularity (Tensor Cores operate on fixed small tile sizes, e.g. 16x16 or similar, depending on generation and precision), requiring the kernel to explicitly manage how the sequence and head dimensions are partitioned into Tensor-Core-sized tiles, rather than treating the operation as one large, unstructured matrix multiply.
- Precision choices: using fp16/bf16 for the matrix multiplications (to engage Tensor Cores) while keeping the softmax's numerically sensitive operations (the exponentiation and normalization) in fp32 internally, converting back to the lower precision only for the final output, balancing Tensor Core throughput against the numerical stability softmax specifically needs.
- Online softmax (a key algorithmic trick): since the full attention-score matrix is never materialized, softmax needs to be computed incrementally (an "online" or "streaming" softmax) as tiles of the score matrix are produced, maintaining a running maximum and running sum that get corrected as new, potentially-larger values are seen, rather than the standard softmax algorithm's assumption that the full row of values is available at once.
- Alignment constraints: tile dimensions and shared-memory buffer strides need to be sized and aligned to the hardware's requirements (e.g. global-memory accesses aligned to 128-byte boundaries for efficient coalescing, and matrix dimensions padded to the Tensor Core's tile-size multiple, as discussed in the Tensor Core tile-shapes topic) so that both the global-memory loads staging data into shared memory and the Tensor Core operations themselves run on their fastest supported path rather than an unaligned, slower fallback.
- Avoiding shared-memory bank conflicts: shared memory is physically divided into banks, and when multiple threads in the same warp read or write different addresses that happen to map to the same bank simultaneously, those accesses serialize instead of completing in parallel, a "bank conflict" that silently degrades the kernel's effective shared-memory bandwidth; staging Q/K/V tiles into shared memory needs a layout that avoids this, typically via padding (adding an extra unused column so a tile's row stride no longer aligns with the bank count) or an explicit swizzled/permuted addressing scheme, a technique used deliberately in FlashAttention-style kernels to keep every thread in a warp hitting a distinct bank.
Worked example
Design choices in code (framework-level, since a full custom CUDA kernel is out of scope for this format): implement attention using PyTorch's torch.nn.functional.scaled_dot_product_attention with a Flash-Attention-style backend selected (which internally performs exactly this fusion and Tensor-Core-tiled computation), or, if building a fully custom kernel, use a library like Triton to write the fused kernel at a higher level of abstraction than raw CUDA while still controlling tile sizes and the online-softmax algorithm explicitly; either path avoids materializing the full O(sequence_length^2) attention-score matrix in HBM, which is the core design win regardless of implementation level.
Trade-offs & pitfalls
Writing a genuinely optimal custom fused attention kernel from scratch (rather than using an existing, heavily-optimized implementation like FlashAttention) is a substantial engineering undertaking, requiring careful tuning of tile sizes for the specific hardware generation and getting the online-softmax numerics exactly right; for most teams, the practical answer is using an existing, well-validated fused-attention implementation rather than reimplementing this from scratch, reserving custom kernel work for cases with genuinely novel attention variants not covered by existing libraries. Validating a custom kernel also needs its own explicit process: check numerical correctness by comparing the kernel's output against a reference eager-mode (unfused) attention implementation using a tolerance-based comparison (e.g. torch.allclose with an atol/rtol appropriate to the reduced precision in use, since fp16/bf16 accumulation will not match fp32 bit-for-bit) across a range of sequence lengths, batch sizes, and edge cases (very short sequences, causal/masked attention, sequences not evenly divisible by the tile size); and set up a performance regression test that benchmarks the kernel's measured throughput/latency against a stored baseline on every change, failing the check if performance regresses beyond a defined threshold, since a kernel change can stay numerically correct while silently becoming slower.
You're planning on-prem GPU procurement for large-scale training. Draft a plan covering GPU model selection, rack and rack-power sizing (kW per rack), cooling requirements, UPS, networking (RDMA, 100GbE), procurement timelines, vendor support, capacity planning for target utilization, and how these physical choices affect training throughput, single-job latency, and total cost of ownership.
Sample Answer
Direct answer
Planning on-prem GPU procurement for large-scale training requires a plan spanning GPU model selection (matched to the actual workload's compute/memory needs), physical infrastructure sizing (rack space and power, since dense GPU nodes draw far more power per rack than typical enterprise servers), and cooling requirements sufficient for that power density, since underestimating any one of these three typically becomes the binding constraint regardless of how well the other two are planned.
Structured elaboration
- GPU model selection: match the specific GPU generation/model to the actual workload requirements (memory capacity per GPU for the target model sizes, precision support needed like native bf16/fp8, and interconnect capability like NVLink generation), rather than defaulting to "the newest/most powerful available," since procurement lead time and cost scale with how cutting-edge the chosen hardware is, and a slightly older generation may be substantially cheaper and faster to procure while still meeting the actual workload's needs.
- Rack and rack-power sizing: dense GPU servers (e.g. 8-GPU nodes with high-end data-center GPUs) can draw substantially more power per rack unit than typical enterprise compute hardware, often requiring specific high-density rack power provisioning (many kW per rack) well beyond what a typical data center's existing rack power allocation provides; this needs to be sized explicitly against the specific GPU model and node density chosen, not assumed to fit within existing, non-GPU-optimized rack power budgets.
- Cooling requirements: power drawn becomes heat that must be removed; at the power densities modern GPU racks require, some data centers need liquid cooling or other high-density cooling solutions beyond standard air cooling, which is both a cost and a facility-capability question that needs to be resolved (does the target facility support this, or does a facility upgrade/different facility choice become necessary) before hardware even arrives.
- Networking infrastructure: beyond the GPUs themselves, the inter-node networking fabric (InfiniBand or high-speed Ethernet, matched to the target training scale's communication needs) needs its own procurement and installation planning, often on a similarly long lead time to the GPUs themselves, and needs to be sized for the target cluster's actual communication pattern (all-reduce-heavy synchronous training needs particularly high bandwidth and low latency between nodes). Concretely this typically means RDMA-capable fabric (InfiniBand, or RoCE over 100GbE or faster Ethernet) rather than standard TCP/IP networking, since RDMA's ability to transfer data between GPUs across nodes without routing through the host CPU is what makes multi-node all-reduce fast enough not to become the dominant bottleneck at scale.
- UPS (uninterruptible power supply): sized to bridge the gap until backup generators engage, or to allow a controlled checkpoint-and-shutdown of in-flight training jobs, since an ungraceful power loss mid-training risks losing the last unsaved checkpoint's worth of progress and can corrupt a checkpoint file that was mid-write at the moment power dropped; UPS capacity needs to be sized against the same power-density numbers used for rack and cooling planning, not treated as a separate, smaller-scale concern.
- Vendor support: negotiate support/SLA contracts with a bounded hardware-replacement turnaround time, since in a large synchronous training job a single failed GPU or failed NIC can stall the entire job until it's replaced or worked around, and on-site spare-parts agreements for the most failure-prone components meaningfully reduce that downtime risk compared to a standard mail-in RMA process.
- Capacity planning for target utilization: provision against a realistic target utilization (commonly in the 70-85% range) rather than assuming the cluster runs at 100% of nameplate capacity continuously, since job-scheduling gaps, planned maintenance windows, and failed-node downtime all reduce achievable utilization below the theoretical maximum; sizing the cluster as if it will hit 100% utilization leads to a plan that can't actually deliver the training throughput it was sized for.
- Lead time and phased procurement: GPU hardware (especially cutting-edge models) can have long procurement lead times (many months, sometimes longer during periods of high industry demand), which needs to be planned well ahead of the target training start date, potentially with a phased procurement approach (securing an initial tranche of capacity while the remainder is still in the supply pipeline) rather than assuming all hardware arrives simultaneously on a fixed date.
Worked example
Planning a 64-GPU on-prem cluster (8 nodes of 8 GPUs each): GPU model selection settles on a specific generation balancing memory-per-GPU against cost and availability lead time; rack power sizing calculates each 8-GPU node's power draw (summing GPU TDP, host CPU/memory/storage draw, and typical power-supply overhead) and provisions rack power circuits with headroom above that calculated draw; cooling capacity is validated against the facility's existing cooling infrastructure, with a liquid-cooling retrofit budgeted if the calculated heat output exceeds what existing air cooling can handle; and procurement is initiated with enough lead time (informed by current vendor-quoted lead times, not optimistic assumptions) before the planned training start date, with network fabric procurement running on a parallel timeline.
Trade-offs & pitfalls
The most common on-prem GPU procurement planning mistake is treating GPU hardware acquisition as the only real constraint and underestimating power/cooling infrastructure needs, which can become the actual bottleneck (a facility physically unable to support the power density of the newly-arrived GPU hardware) well after the (harder-to-quickly-fix) hardware procurement itself is complete; power and cooling capacity should be validated and, if necessary, upgraded on a timeline that keeps pace with hardware procurement, not treated as an afterthought to be solved once hardware arrives. Each of these choices also has a direct, traceable effect on throughput, latency, and total cost of ownership: insufficient rack power or cooling headroom forces GPUs to thermal-throttle, directly reducing achieved training throughput below the hardware's rated capability regardless of how well everything else was planned; insufficient network bandwidth caps achievable scaling efficiency as GPU count grows (per the earlier scaling-efficiency discussion), which shows up as worse single-job latency at scale; and TCO must account for ongoing power, cooling, and support-contract operating costs, not just GPU sticker price, since a cheaper GPU with worse power efficiency or a weaker support contract can end up costing more over its operating lifetime than a pricier, better-supported alternative.
Explain best practices for creating containerized, reproducible training environments. What should be included in the container image (OS libs, CUDA/cuDNN versions, pip/conda packages), and how do you ensure experiments are reproducible across image versions and host kernels?
Sample Answer
Direct answer
A reproducible containerized training environment pins every layer of the software stack INSIDE the image (OS/system libraries, CUDA/cuDNN, framework and dependency versions, code) as a versioned, immutable image, and additionally accounts for the parts of the stack that live OUTSIDE the container on the host, principally the host's NVIDIA GPU driver and kernel version, which containerization alone does not pin.
Structured elaboration
- Base OS and system libraries: pin the base image to a specific tag, including specific versions of system-level libraries.
- CUDA/cuDNN versions: pin exact CUDA and cuDNN versions matching what the framework was validated against.
- Framework and dependency versions: pin exact versions for the framework and every dependency in a lockfile-style manifest (pip's
requirements.txtwith==pins, or a conda lockfile for conda-managed environments). - Code and configuration: bake the training code (or a specific commit hash reference) into the image, or record the commit hash alongside the image tag.
- Host kernel and GPU driver, the part containerization does NOT pin: for GPU workloads, the NVIDIA driver is installed on the HOST machine, not inside the container; the container only ships the CUDA TOOLKIT (compiler, runtime libraries), which must be compatible with, but is architecturally separate from, whatever driver version the host happens to have installed. Two hosts running the byte-identical container image can still produce different behavior (or fail to run at all) if their host driver versions differ enough to fall outside the CUDA toolkit's supported driver-compatibility range, or, more subtly, if a driver update changes low-level kernel scheduling or floating-point behavior in a way that affects numerical results at the margins. The host's Linux KERNEL version matters similarly for anything relying on kernel-level behavior the container doesn't isolate (e.g. specific NCCL/RDMA driver interactions, GPU peer-to-peer access configuration), which is invisible to and unmanaged by the container image itself.
- Mitigations for the host-side gap: document and enforce a MINIMUM supported host driver version (and ideally a validated, narrow range) alongside the image tag, since "any driver new enough to run this CUDA version" is a looser reproducibility bar than "this exact validated driver version"; where infrastructure allows it, standardize the host driver/kernel version across the fleet via the same infrastructure-as-code discipline applied to the container image itself (e.g. a pinned host AMI/base image for the node pool), rather than treating the host environment as out of scope simply because it's outside the container boundary.
- Reproducible builds: use a version-controlled Dockerfile that produces a deterministic image, and tag/publish images immutably.
Worked example
A training image tagged training:v2.3.1-cuda12.1-cudnn8.9-torch2.1.0 runs correctly and reproducibly on host A (driver 535.104) and host B (driver 550.90.07), both within CUDA 12.1's supported driver range, so the container-internal stack is identical, but a subtle numerical difference in one specific fused kernel is later traced to the driver version difference, not anything inside the image; the fix is documenting a validated driver version (or narrow range) as part of the reproducibility contract, not just the image tag, and re-running the validation suite whenever the fleet's host driver is upgraded.
Trade-offs & pitfalls
Pinning every version this strictly trades convenience for reproducibility guarantees. The host driver/kernel gap is a common blind spot precisely because it's easy to assume containerization solves reproducibility completely; teams that only pin the image and never document or standardize the host driver version can spend significant debugging time chasing an apparent "non-determinism" that's actually a host-environment difference the container never controlled.
Unlock Full Question Bank
Get access to all Model Training Infrastructure and Distributed Training interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.