LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnInference & Production ScaleGPU Failure Operations
⚙️HardMLOps & Deployment

GPU Failure Operations

Diagnose one failing GPU replica, contain the smallest safe scope, preserve evidence, and re-admit hardware through explicit gates.

24 min read
Learning path
Step 163 of 196 in the full curriculum
GPU Serving & AutoscalingDistributed Inference Data Plane

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

In this synthetic incident, request r-7812 asks replica summarizer-7f9d6 for another 1.50 GiB at 14:03:17 UTC on August 29, 2026. The allocation fails. Node gpu-a17 still answers health checks, peer replicas still serve traffic, and the alert says only CUDA out of memory. The timestamps, shortened GPU IDs, and rounded memory values are teaching data, not measurements from a real fleet.

The first receipt is more specific:

failure receipt
1node=gpu-a17 pod=summarizer-7f9d6 gpu=GPU-7f3 2capacity=40.00 GiB device_free=0.62 GiB 3pytorch_allocated=30.10 GiB pytorch_reserved=36.70 GiB 4inactive_split_blocks=6.10 GiB largest_inactive_split_block=0.88 GiB 5allocation_request=1.50 GiB 6nvml_device_used=39.38 GiB new_xids=[] new_uncorrectable_ecc=0

There is no universal repair command after this receipt. A request retry, process restart, device quarantine, and node drain act at different scopes. First stop new work reaching the failing replica. Then use evidence to choose the smallest sufficient repair scope.

Why is CUDA out of memory insufficient evidence for draining gpu-a17?

Answer

The error names a failed allocation in one process. It doesn't yet distinguish live application demand, allocator fragmentation, memory held outside PyTorch, a stale process, or a device fault. Draining the node would evict unrelated workloads before that scope is known.

Build an incident receipt before changing state

An incident receipt is a time-aligned record of request, process, device, node, and cluster evidence. The serving lesson established admission and readiness controls; here they isolate a failing worker while you investigate. PyTorch can record allocator history and dump a snapshot for memory_viz, its memory visualizer. A snapshot includes allocator state and OOM events, but only for memory visible to that allocator.[1]Reference 1Understanding CUDA Memory Usagehttps://docs.pytorch.org/docs/main/torch_cuda_memory

For r-7812, preservation comes before restart:

  1. Remove the replica from application readiness so new work stops arriving.
  2. Record request ID, pod UID, container restart count, PID, node, GPU UUID, model revision, allocator backend and configuration, CUDA runtime, driver, and timestamps.
  3. Dump the PyTorch memory snapshot if the process still responds.
  4. Record device-wide memory, process accounting, ECC counters, clocks, power, temperature, Xid events, and device-plugin health.
  5. Copy logs and artifacts to incident storage with access controls.
  6. Only then choose containment and repair scope.

A process exit destroys unsaved allocator history. A reset or reboot can erase volatile device evidence and logs. Capture what you can within a bounded incident deadline; don't delay required isolation or termination while a broken process hangs on a snapshot call. Preservation isn't permission to collect another tenant's prompts, model inputs, or secrets.

Synthetic 40 GiB device: 30.10 GiB allocated, 6.60 GiB other allocator reserve, 2.68 GiB outside reserve, 0.62 GiB free. The largest inactive split block is 0.88 GiB, below the 1.50 GiB request despite 6.10 GiB across all split blocks.
Allocated memory is inside reserved memory, not an extra allocation to add on top. The bottom comparison exposes the fragmentation clue: 6.10 GiB in total fragments isn't one 1.50 GiB block. It doesn't rule out outside-PyTorch pressure or other allocator pools.

The receipt separates several memory quantities:

ViewExact valueWhat it can supportWhat it can't prove
PyTorch allocated30.10 GiBLive tensor blocks known to allocatorWhich tensor is semantically necessary
PyTorch reserved36.70 GiBSegments allocator still holdsContiguous availability for a 1.50 GiB request
Reserved minus allocated6.60 GiBAllocator accounting gap to reconcile in snapshotBytes currently inactive and reusable
Inactive split blocks6.10 GiBFree fragments trapped in partly active segments at OOMOne reusable block of sufficient size
Largest inactive split block0.88 GiBLargest observed fragment in snapshotFuture allocation layout after workload changes
NVML device used39.38 GiBWhole-device usage across CUDA usersOwnership without process or subsystem attribution
NVML used minus reserved2.68 GiBApproximate use outside PyTorch reserveWhether NCCL, another process, or driver state owns it

reserved - allocated is an accounting gap, not a reusable-byte counter. The snapshot's 6.10 GiB of inactive split blocks suggests fragmentation, because its largest observed fragment is only 0.88 GiB. Inspect segments, pending frees, stream ordering, and allocator pools before claiming those are all possible sources of space. A free fragment in one segment can't simply be added to a nonadjacent fragment to satisfy one allocation.

The outside-PyTorch delta also matters. The request exceeds device-free memory by 1.50 - 0.62 = 0.88 GiB; the 2.68 GiB delta is larger than that deficit. Releasing some of it could change the outcome, but you haven't established who owns it or whether it can be released. Fragmentation under memory pressure is a working hypothesis, not proof of one exclusive cause.

The subtraction assumes the same physical GPU, compatible accounting scope, and nearly simultaneous samples. Match GPU UUID and, when applicable, MIG instance identity. Missing NVML readings, counter resets, or mismatched device scopes are missing evidence, never zero usage.

Keep memory layers separate

GPU memory pressure has four common software layers. Combining them into one “leak” diagnosis produces the wrong repair.

LayerStrong evidenceTypical containmentRepair question
Application allocationsAllocated memory tracks batch, sequence, KV cache, workspace, or retained tensorsReject, shed, or reroute bounded workWhich live state exceeded the admission envelope?
Allocator reservationReserved stays above allocated; snapshot shows inactive blocks and split segmentsRemove replica, preserve snapshot, restart process if policy allowsIs layout fragmented, or is cached reserve expected?
Non-PyTorch allocationNVML/device use materially exceeds PyTorch reserveAttribute libraries and processes before tuning allocatorDoes NCCL, direct CUDA allocation, or another framework own it?
Process leakDevice process list shows stale or duplicate owners after expected teardownStop admission to affected device; process owner cleans up within policyWhich lifecycle failed to release the process or context?

PyTorch explicitly warns that its memory profiler can't see allocations made directly through CUDA APIs. NCCL is a documented example. torch.cuda.device_memory_used() provides a device-wide cross-check, and NVML exposes device and process telemetry for independent attribution.[1]Reference 1Understanding CUDA Memory Usagehttps://docs.pytorch.org/docs/main/torch_cuda_memory[2]Reference 2NVML API Reference Guidehttps://docs.nvidia.com/deploy/nvml-api/nvml-api-reference.html

Don't treat reserved - allocated as wasted memory by definition. The caching allocator holds segments so later allocations avoid expensive device synchronization. Fragmentation becomes plausible when an OOM snapshot shows enough inactive split bytes but no fragment large enough for the failed request. PyTorch allocator configuration can change split behavior, yet tuning it before identifying the workload shape can hide an admission-control bug.[3]Reference 3CUDA semanticshttps://docs.pytorch.org/docs/stable/notes/cuda.html

This receipt assumes PyTorch's native caching allocator. With backend:cudaMallocAsync, some allocator statistics have backend-specific or undefined meaning, and native split-block tuning options don't apply. Record the backend and use its documented evidence instead of copying this inference unchanged.[3]Reference 3CUDA semanticshttps://docs.pytorch.org/docs/stable/notes/cuda.html

Record a finite allocator history

Enable history before the incident window when overhead and privacy policy permit:

allocator-history.py
1import torch 2 3torch.cuda.memory._record_memory_history( 4 enabled="all", 5 context="all", 6 stacks="python", 7 max_entries=100_000, 8) 9 10torch.cuda.memory._dump_snapshot("r-7812-memory.pickle")

This is a CUDA-only instrumentation fragment, not a runnable CPU diagnostic. Enable history before the workload and dump it from that same process near the failure; the two adjacent calls here show the API, not an observation window. The initial _ marks private APIs, so pin and validate the fleet's PyTorch version. PyTorch says memory_viz processes the file locally without uploading it.[1]Reference 1Understanding CUDA Memory Usagehttps://docs.pytorch.org/docs/main/torch_cuda_memory Treat snapshots as sensitive artifacts: stack traces and source paths can expose application details.

History is a ring buffer, not an infinite flight recorder. Once max_entries fills, the oldest entries are replaced. Large histories can produce multi-gigabyte snapshots. Set a bounded window, record the start time and entry limit in the receipt, and trigger a dump near the failure. A snapshot with no OOM event may mean capture began too late or history wrapped, not that the alert was false.

A snapshot shows 6.10 GiB across inactive split blocks, but NVML reports 2.68 GiB more device use than PyTorch reserved. What should you conclude?

Answer

Two hypotheses remain. Allocator layout may block the 1.50 GiB request, while another CUDA user owns about 2.68 GiB. Inspect snapshot blocks and attribute device processes or libraries. Neither number alone proves a leak.

Classify beyond memory

An OOM can be the visible end of a different failure. A collective stalls, a peer disappears, requests accumulate, and healthy ranks hold buffers until an allocation fails. Build a parallel device and node view. NVML is NVIDIA's Management Library; DCGM is its Data Center GPU Manager. ECC means error-correcting code memory protection. An Xid is a driver-reported error code, not a verdict that the physical GPU is broken.

Fault classEvidence to correlateWhy symptom can misleadInitial scope
ECC or device faultNew uncorrectable ECC, GPU UUID, kernel timestamp, device healthOOM or timeout can follow lost device accessDevice or node quarantine pending memory-error guidance
Xid eventExact code, GPU UUID, kernel timestamp, catalog action, nearby eventsSame code family can reflect application, NVIDIA software, or hardwareScope named by event-specific catalog and surrounding evidence
PCIe or NVLink faultDCGM PCIe, NVLink, nvbandwidth, or NCCL test; link counters; peer topologyOne slow or failed rank appears as a distributed timeoutAffected GPU topology, then node if isolation is unavailable
Clock limitingExact clock-event reasons, configured limits, temperature, power, clocks, workload phaseAn expected power cap and a thermal fault can both reduce clocksReplica first; platform path if unexpected under controlled load
Driver or runtime faultDriver/runtime versions, module logs, NVML initialization, DCGM software testApplication sees initialization or unknown CUDA errorStop admission; platform owner validates stack contract
CUDA process-state faultExact CUDA error, first failing operation, synchronization pointAsynchronous execution reports an earlier failure laterProcess, unless device evidence expands scope

NVML clock-event reasons name the active limiter, not its root cause. GPU idle and configured application clocks can be expected. Software power cap means clocks are respecting a configured power limit, while thermal slowdown points to temperature protection. Correlate reason, workload phase, configured limits, measured power, and temperature before calling it a fault.[2]Reference 2NVML API Reference Guidehttps://docs.nvidia.com/deploy/nvml-api/nvml-api-reference.html

An Xid entry is not a root cause label. NVIDIA states that Xid events can arise from hardware, NVIDIA software, or an application. Recovery actions differ by event, and newer catalog guidance can attach a specific recovery action to the reported event.[4]Reference 4Introduction to Xid Errorshttps://docs.nvidia.com/deploy/xid-errors/introduction.html[5]Reference 5Analyzing Xid Errors Using the Xid Cataloghttps://docs.nvidia.com/deploy/xid-errors/analyzing-xid-catalog.html

The GPU Operator device plugin listens for health events and can report a GPU unhealthy. Kubernetes then lowers allocatable device count, but pods already assigned to that device remain assigned and may fail or crash-loop.[6]Reference 6NVIDIA GPU Operator Troubleshootinghttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/26.3/troubleshooting.html[7]Reference 7Device Pluginshttps://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/ Application readiness and workload containment still need an explicit controller or operator action. Device-plugin health alone is not retrospective eviction.

Respect asynchronous error reporting

CUDA work is asynchronous. An API call can enqueue work and return before the device executes it; an error may surface at a later synchronization boundary. Capture the first observed failure, stream, request, kernel, and correlation timestamp. CUDA_LAUNCH_BLOCKING=1 can help reproduce ordering in a controlled debug run, but it changes execution and should not become a fleet-wide production setting.[8]Reference 8CUDA Programming Guide.https://docs.nvidia.com/cuda/cuda-programming-guide/

Some CUDA runtime errors explicitly leave the process in an inconsistent state. NVIDIA documents illegal address, kernel-execution launch timeout, launch failure, and several hardware-stack errors as requiring process termination and relaunch. Retrying another request in that same process is unsafe. This rule doesn't apply to every CUDA error, so preserve the exact error enum and originating API operation rather than matching the word “CUDA.”[9]Reference 9CUDA Runtime API Error Typeshttps://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__TYPES.html

Contain at smallest broken scope

Use a ladder. Move outward only when evidence says the smaller boundary can't protect users or hardware.

ActionAppropriate evidenceWhat must be true firstWhy a broader action is risky
Retry request elsewhereIdempotent or deduplicated request; healthy alternate replica; failed process still trustworthy or excludedRetry budget and side-effect contract permit replayBlind retries amplify memory pressure and duplicate effects
Remove replica from readinessOne worker is unhealthy or near its memory envelopeGateway and scheduler honor readiness quicklyTraffic can keep reaching a process that should be preserved
Restart processAllocator fragmentation, process leak owned by replica, or fatal CUDA process-state errorBounded evidence capture attempted; restart budget permits itRestart erases volatile evidence and can loop on a bad device
Quarantine GPUNew uncorrectable ECC, isolation-requiring Xid action, fabric finding, or repeated device-scoped evidenceDevice identity and cluster owner are knownShared node may lose capacity; peer topology can be affected
Cordon or drain nodeNode-wide driver, fabric, power, cooling, or repair requirementPlatform owner authorizes scope; workload disruption reviewedDrain can evict unrelated tenants and destroy local ephemeral data

Cordon and drain aren't synonyms. Cordoning makes the node unschedulable for ordinary new placements; it doesn't evict existing pods. Draining requests workload eviction and may wait on disruption budgets or other blockers. Removing a replica from readiness also doesn't cancel in-flight requests or immediately close every existing connection. Confirm the actual admission boundary before restarting anything.[10]Reference 10Automated Driver Upgradehttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-driver-upgrades.html

Diagram showing Replica fails; stop its admission, Bounded evidence capture, Classify smallest broken scope, and request or process.
Replica fails; stop its admission, Bounded evidence capture, Classify smallest broken scope, and request or process.

For r-7812, rerouting a retry still requires an idempotent or deduplicated operation. The failed replica leaves readiness, with in-flight requests handled separately. Capture its snapshot and receipt if possible. OOM alone doesn't require process relaunch, but policy may choose one to contain recurring allocator pressure. The supplied receipt has no new ECC or Xid events; link, thermal, and power evidence still need collection. Absence of those fields isn't proof they passed. Nothing supplied yet justifies a node drain.

An illegal-address error appears after a request, but the next health check passes. May the worker serve another request?

Answer

No. CUDA documents illegal address as leaving the process in an inconsistent state. Remove the worker from readiness, preserve evidence, terminate and relaunch the process, then apply re-admission gates. A passing application probe doesn't repair CUDA process state.

Run diagnostics with an explicit question

DCGM diagnostics are active tests, not repair commands. NVIDIA describes four levels:

DCGM levelIntended operational useRepresentative additionsScheduling rule
Level 1Fast readiness signal before workDeployment and software checksMay fit an admission gate after local validation
Level 2Failure epilogue or brief health checkPCIe, memory, memory bandwidth, NVLinkRun outside user traffic when tests can contend
Level 3Admin post-mortemDiagnostic stress, targeted power/stress, nvbandwidth, NCCL testsQuarantined or idle hardware only
Level 4Extended post-mortemLonger memory and pulse-style coverageMaintenance window with platform ownership

Exact tests depend on DCGM version, hardware, driver, and installed plugins. In the current run-level table, pcie covers PCIe and NVLink checks; nvbandwidth and nccl_tests start at Level 3, not Level 2. A named test may be unavailable. Pass applies only to checks that ran, Fail may be a device finding or setup error, and Skip or Not Run supplies no health verdict.[11]Reference 11DCGM Diagnosticshttps://docs.nvidia.com/datacenter/dcgm/latest/user-guide/dcgm-diagnostics.html[12]Reference 12DCGM Diagnostic Pluginshttps://docs.nvidia.com/datacenter/dcgm/latest/reference/diagnostics/plugins/index.html

Ask one question per run:

  • “Can this GPU enumerate and pass deployment checks?” points toward Level 1.
  • “Did memory or PCIe fail around this incident?” points toward selected Level 2 tests.
  • “Can the quarantined tensor-parallel topology sustain fabric traffic?” points toward nvbandwidth or NCCL plugins at an admin level.
  • “Does the device reproduce a memory or power failure under burn-in?” points toward selected stress tests on idle hardware.

Record command, DCGM version, selected entities, test names, parameters, wall time, plugin availability, raw result, and exit status. DCGM doesn't claim comprehensive diagnosis or automatic repair. A passing suite narrows evidence; it doesn't erase an Xid or guarantee future health.[11]Reference 11DCGM Diagnosticshttps://docs.nvidia.com/datacenter/dcgm/latest/user-guide/dcgm-diagnostics.html

Make ownership part of automation

A multi-tenant GPU node has four ownership boundaries, even if one team handles several:

BoundaryOwner decisionAutomation may do safelyEscalation trigger
RequestServing teamBound retries, deduplicate effects, route away from unhealthy replicaSide-effect ambiguity or exhausted retry budget
Process or podWorkload ownerToggle readiness, preserve app receipt, restart within disruption budgetRepeated crash or cross-process memory owner
GPU devicePlatform GPU controllerMark device unavailable, attach evidence, stop new allocationNew uncorrectable ECC, isolation-requiring Xid action, fabric finding, or repeated burn-in failure
Node and rackCluster or hardware ownerCordon, drain, repair, reboot, or replace under policyShared driver, cooling, power, PCIe, or topology fault

Error-aware automation consumes structured facts, not log substrings alone. A useful event includes GPU UUID, node UID, workload UID, process identity, exact CUDA or Xid code, source, first and last timestamps, recurrence count, and evidence links. Its transition should be idempotent: one device fault creates one quarantine record, not a storm of repeated drains.

Never let a workload controller reset a shared GPU or drain a node by inference. NVIDIA's own GPU Operator upgrade workflow separates cordon, workload termination, validation, and uncordon. Its documentation warns that full drain can evict unrelated pods and can permanently remove emptyDir data.[10]Reference 10Automated Driver Upgradehttps://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-driver-upgrades.html Production remediation needs equivalent scope checks and authority.

Preserved evidence also needs tenancy controls:

  • Snapshot allocator metadata, not prompt bodies, unless incident policy explicitly requires content.
  • Restrict process lists and command lines when they expose another tenant's paths or arguments.
  • Attach retention, encryption, and access policy to receipts.
  • Store stable IDs and hashes so responders can correlate without copying sensitive payloads.

Repair path for gpu-a17

The repair is intentionally narrow:

  1. Contain: Set summarizer-7f9d6 not ready. Stop scheduler admission to its process.
  2. Preserve: Save snapshot, application logs, exact versions, NVML memory and process view, ECC counters, clocks, power, temperature, and kernel Xid window.
  3. Classify: Confirm 30.10 GiB allocated, 36.70 GiB reserved, 6.10 GiB inactive across split blocks, 0.88 GiB largest fragment, and 39.38 GiB device-wide use. Attribute the 2.68 GiB delta.
  4. Repair process: Finish or reject in-flight work according to the request contract. Relaunch the serving process under its normal supervisor.
  5. Prove baseline: Load the same model revision and configuration. Confirm expected idle memory and the expected process owners for this isolation mode.
  6. Burn in: Replay a bounded canary workload that includes the 1.50 GiB allocation shape. Watch allocator headroom, device-wide delta, Xid/ECC, link status, clocks, temperature, power, and latency.
  7. Re-admit: Restore only a small traffic fraction. Expand after a fixed observation window with no gate failure.

If fragmentation returns under the same bounded workload, process restart was containment, not repair. Revisit admission envelopes, KV-cache sizing, batch and sequence caps, workspace lifetime, CUDA graph pools, and allocator configuration. If outside-PyTorch use grows, attribute NCCL, custom CUDA, peer processes, or context lifecycle before changing allocator settings.

Re-admission gates

Use explicit pass/fail gates rather than “looks stable”:

GateExample evidenceFailure action
IdentityExpected GPU UUID, driver/runtime pair, model revision, and process owners for the isolation modeHold admission and resolve inventory mismatch
Idle baselineDevice-wide and allocator memory inside known bandInvestigate stale process, context, or changed model footprint
Functional probeDeterministic canary returns expected shape and statusKeep replica out of readiness
Memory envelopePeak allocated, reserved, largest reusable block, and outside delta remain within policyAdjust workload or allocator plan before retry
Device healthNo new disqualifying Xid/ECC; required DCGM checks ran and passedKeep quarantined; follow event-specific owner runbook
Fabric healthRequired peer path and selected fabric tests pass on affected topologyKeep topology unavailable
Thermal and powerClocks, temperature, and power within workload-approved bands during bounded loadInvestigate unexplained limits before escalating cooling, power, or hardware
SoakFixed request count or duration completes without recurrenceExtend quarantine and compare receipts

Burn-in must resemble the failed allocation and communication shape without carrying production traffic. “One inference succeeded” misses fragmentation that emerges after many allocation cycles and fabric faults that need multi-GPU load. Define duration, load, pass thresholds, and abort conditions before starting.

A diagnostic receipt reports PCIe Pass and nvbandwidth Skip. Can automation re-admit a topology whose incident requires bandwidth coverage?

Answer

No. PCIe Pass covers only the check that ran. Skip is no health verdict, and the missing fabric coverage is relevant to the incident. Keep the topology quarantined until the required test can run or an authorized owner chooses another evidence path.

A small coverage check makes the distinction executable. Assume these results came from one fresh, identified run on the required GPU topology. The function checks only diagnostic coverage, not the other re-admission gates:

diagnostic-coverage.py
1def coverage_complete(required, results): 2 if not required: 3 raise ValueError("declare required tests before running diagnostics") 4 return ( 5 all(results.get(name) == "Pass" for name in required) 6 and "Fail" not in results.values() 7 ) 8 9required = {"pcie", "nvbandwidth"} 10for status in ("Skip", "Not Run", "Fail", "Pass"): 11 results = {"pcie": "Pass", "nvbandwidth": status} 12 complete = coverage_complete(required, results) 13 assert complete == (status == "Pass") 14 print(f"nvbandwidth={status:7} coverage_complete={complete}") 15assert not coverage_complete(required, {"pcie": "Pass"}) 16assert not coverage_complete(required, { 17 "pcie": "Pass", "nvbandwidth": "Pass", "memory": "Fail", 18}) 19try: 20 coverage_complete(set(), {}) 21except ValueError: 22 pass 23else: 24 raise AssertionError("an empty plan must not pass vacuously")
Output
1nvbandwidth=Skip coverage_complete=False 2nvbandwidth=Not Run coverage_complete=False 3nvbandwidth=Fail coverage_complete=False 4nvbandwidth=Pass coverage_complete=True

Even the final True isn't permission to unquarantine. Identity, telemetry freshness, process state, workload canaries, ownership, and the other required gates must still pass.

Downloadable receipt analyzer

The fixture contains eight synthetic receipts spanning allocator fragmentation, application capacity, outside-PyTorch ownership, device fault, fabric fault, clock limiting, process-corrupting CUDA error, and driver/runtime failure.

  • Download fixture
  • Download read-only analyzer

The analyzer is a read-only worksheet. It doesn't connect to hardware, run diagnostics, or change cluster state. It emits a primary hypothesis and a separate must_relaunch flag so a hardware finding can't hide an unsafe process state. A false flag means only “no listed relaunch-required error,” not “healthy.”

Its inputs are already normalized. new_xids and ECC increments cover one incident window; an empty list or zero counter requires a successful collection, not a failed telemetry query. clock_event_reasons includes only limiters correlated with an unexpected regression. An operator or version-pinned parser has decoded DCGM defect classes from the full code and message; raw Fail, Skip, and Not Run aren't defect classes. CUDA labels come from exact enums and API context, not substring matches. The relaunch set is illustrative, not an exhaustive replacement for the CUDA catalog.[9]Reference 9CUDA Runtime API Error Typeshttps://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__TYPES.html

For memory arithmetic, samples must share device scope and time. Missing memory readings use JSON null. The analyzer rejects nonfinite, negative, and contradictory numbers rather than clamping them into a plausible result. Native split-block logic runs only for allocator_backend="native". The 4.0 GiB outside-PyTorch threshold is a fixture policy, not a universal alarm threshold.

Run the downloadable analyzer from the article directory. The code below executes that same source, avoiding a second implementation that could drift:

analyze-synthetic-receipts.py
1import runpy 2 3runpy.run_path("assets/analyze_gpu_receipts.py", run_name="__main__")
Output
1r-7812: allocator-fragmentation | outside=2.68 GiB | must_relaunch=False 2r-7813: application-capacity | outside=0.20 GiB | must_relaunch=False 3r-7814: outside-pytorch | outside=16.40 GiB | must_relaunch=False 4r-7815: device-memory-fault | outside=1.10 GiB | must_relaunch=False 5r-7816: fabric-fault | outside=1.00 GiB | must_relaunch=False 6r-7817: clock-limited | outside=1.00 GiB | must_relaunch=False 7r-7818: process-corrupted | outside=0.70 GiB | must_relaunch=True 8r-7819: driver-runtime | outside=unknown | must_relaunch=False

For r-7813, live allocation plus the request is 39.10 + 1.00 = 40.10 GiB, above the fixture's entire 40 GiB capacity. That supports reducing live demand even before attributing other users. For r-7819, NVML initialization failed: its outside-PyTorch value must remain unknown, not 0.00 GiB. Neither a hypothesis nor a false relaunch flag authorizes re-admission.

When two signals arrive together

Suppose r-7818 reports both illegal address and an Xid. The Xid still needs catalog interpretation, but the process-relaunch requirement can't wait for that classification. Predict both outputs before running this extension:

mixed-signal-receipt.py
1import json 2import runpy 3from pathlib import Path 4 5analyze = runpy.run_path("assets/analyze_gpu_receipts.py")["analyze"] 6rows = json.loads(Path("assets/gpu_failure_receipts.json").read_text()) 7mixed = dict(rows[6], new_xids=[31]) 8result = analyze(mixed) 9assert result["hypothesis"] == "xid-event" 10assert result["must_relaunch"] is True 11print(result["hypothesis"], "| process relaunch required:", result["must_relaunch"]) 12 13missing = dict(rows[0], nvml_device_used_gib=None) 14result = analyze(missing) 15assert result["hypothesis"] == "incomplete-memory" 16assert result["outside_gib"] is None 17print(result["hypothesis"], "| outside memory:", result["outside_gib"]) 18 19async_allocator = dict(rows[0], allocator_backend="cudaMallocAsync") 20assert analyze(async_allocator)["hypothesis"] == "oom-unresolved" 21print("native fragmentation inference withheld for cudaMallocAsync")
Output
1xid-event | process relaunch required: True 2incomplete-memory | outside memory: None 3native fragmentation inference withheld for cudaMallocAsync

These are local classification checks, not injected GPU failures. Real automation also needs authenticated ownership, sample freshness, incident deduplication, and a durable quarantine state. A later receipt with no new events mustn't clear an existing quarantine. Re-admission requires its own authorized transition through the gates above.

Pitfalls that widen blast radius

  • Calling cached reserve a leak. Reserved memory is allocator policy; snapshot block history decides whether fragmentation is plausible.
  • Reading NVML delta as proof of another process. Direct CUDA, NCCL, libraries, and peer processes all need attribution. PyTorch-managed CUDA graph pools can already be inside its reserve.
  • Retrying in a corrupted CUDA process. Exact runtime error semantics decide whether relaunch is mandatory.
  • Treating every Xid alike. Xid is a structured clue; catalog guidance and surrounding evidence decide scope.
  • Treating Skip as Pass. Missing plugin coverage can't satisfy a readiness gate.
  • Restarting before preservation. The restart may clear the only allocator or kernel evidence.
  • Draining for convenience. Shared-node eviction and ephemeral-data loss require platform authority and review.
  • Re-admitting after one probe. Short probes miss allocation-cycle fragmentation, topology load, and thermal soak failures.

Check your understanding

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.A snapshot reports 6.10 GiB across inactive split blocks, a 0.88 GiB largest fragment, and a failed 1.50 GiB request. Which conclusion is strongest?

Correct answer: Fragmentation is plausible because inactive split total exceeds the request but the largest fragment doesn't.

Block layout supports fragmentation as a working hypothesis. Application pressure and outside-PyTorch use still need attribution.

2.PyTorch reserved memory is 18.0 GiB while NVML device use is 34.4 GiB. What is the best next step?

Correct answer: Attribute direct CUDA, library, and process owners before changing the allocator policy.

The delta sits outside PyTorch's allocator view, but the receipt hasn't identified its owner.

3.Why can a memory snapshot omit an OOM event even when the alert is valid?

Correct answer: Finite history may start late or overwrite older entries after reaching its entry limit.

PyTorch records a bounded history. Late capture and ring-buffer overwrite can remove the relevant event.

4.A worker reports cudaErrorIllegalAddress, then passes its HTTP health check. What action fits CUDA's documented process state?

Correct answer: Remove readiness, preserve evidence, terminate the process, and relaunch it.

Illegal address leaves the CUDA process inconsistent. That evidence alone doesn't expand scope to the node.

5.A device plugin marks one GPU unhealthy on a node with an already assigned pod. What does Kubernetes guarantee?

Correct answer: Allocatable device count falls, while the assigned pod may remain and continue failing.

Device health changes future allocation. Existing assignments and application readiness need separate handling.

6.Which response best preserves evidence for one OOM replica with no device-fault signal?

Correct answer: Stop replica admission, capture allocator and device receipts, then choose restart scope.

This contains user impact while retaining volatile process and device evidence.

7.DCGM reports PCIe Pass and nvbandwidth Skip after a multi-GPU timeout. Which interpretation is correct?

Correct answer: The PCIe check passed, while required bandwidth coverage remains unknown.

Pass and Skip describe different coverage. Skip supplies no health verdict.

8.A shared node has repeated power-cap clock events only under burn-in. Which boundary should decide node repair?

Correct answer: Platform or hardware owner, using power, thermal, clock, and workload evidence.

Configured power caps can be expected under load. The platform owner must compare limits and observed behavior before deciding whether any repair is needed; the event alone doesn't prove a hardware fault.

9.After restarting r-7812's process, which burn-in most directly tests the original hypothesis?

Correct answer: Replay bounded allocation cycles including the 1.50 GiB shape while tracking block layout and device delta.

The burn-in reproduces allocation size and lifecycle while observing allocator and device-wide views.

9 questions remaining.

Next Step
Continue to Distributed Inference Data Plane

Carry the same evidence, ownership, and retry boundaries across routing, <span data-glossary="prefill">prefill</span>, KV transfer, and decode workers.

PreviousGPU Serving & Autoscaling
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

Understanding CUDA Memory Usage

PyTorch Contributors · 2026 · Official documentation

https://docs.pytorch.org/docs/main/torch_cuda_memory

NVML API Reference Guide

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/deploy/nvml-api/nvml-api-reference.html

CUDA semantics

PyTorch Contributors · 2026

https://docs.pytorch.org/docs/stable/notes/cuda.html

Introduction to Xid Errors

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/deploy/xid-errors/introduction.html

Analyzing Xid Errors Using the Xid Catalog

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/deploy/xid-errors/analyzing-xid-catalog.html

NVIDIA GPU Operator Troubleshooting

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/26.3/troubleshooting.html

Device Plugins

Kubernetes Authors · 2026 · Official documentation

https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/

CUDA Programming Guide.

NVIDIA · 2026

https://docs.nvidia.com/cuda/cuda-programming-guide/

CUDA Runtime API Error Types

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__TYPES.html

Automated Driver Upgrade

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-driver-upgrades.html

DCGM Diagnostics

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/dcgm-diagnostics.html

DCGM Diagnostic Plugins

NVIDIA · 2026 · Official documentation

https://docs.nvidia.com/datacenter/dcgm/latest/reference/diagnostics/plugins/index.html

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.