After studying this material, you should be able to:
Goodput = the proportion of time your GPUs spend on productive computation rather than waiting or recovering from failures
Think of it like a factory assembly line:
Use this mental model:
Each GPU has ~1% annualized failure rate
256-GPU job, 30 days → 19% chance of failure
1,024-GPU job, 30 days → 57% chance of failure
Real-world example: The 608 H100 "Delta" supercomputer saw failures every 1.9 hours. For a 32-GPU job, that means a failure roughly every 36 hours.
Your training job will fail. The question is: how much work do you lose when it does?
A snapshot of your training state saved to storage so you can resume from that point after a failure, rather than starting over.
Expected wasted work per failure ≈ ½ × checkpoint interval
Checkpoint every 24 hours → lose ~12 hours of work on average
Checkpoint every 30 minutes → lose ~15 minutes of work on average
torch.save on Rank 0 ❌ (Avoid)What happens:
[Rank 0] → Gathers ALL model state → Writes entire file → Done
[Rank 1] → Waits...
[Rank 2] → Waits...
[Rank N] → Waits...
Problems:
What happens:
[Rank 0] → Writes its own shard ─┐
[Rank 1] → Writes its own shard ├─ All in PARALLEL
[Rank 2] → Writes its own shard │
[Rank N] → Writes its own shard ─┘
└→ .metadata file written last
Advantages:
| Feature | Benefit |
|---|---|
| Parallel writes | Save time scales as 1/N with number of ranks |
.metadata file | Records global layout; enables recovery on different GPU counts |
| Works for DDP too | Not just sharded models — all training styles benefit |
| Future-proof | Same API works when you move to FSDP or tensor parallelism |
The .metadata file is critical: It is written only after all shards complete. Its presence = trustworthy signal that the checkpoint is valid.
async_save ✅✅ (Best)Even DCP blocks training until bytes are written to storage. async_save solves this:
Standard DCP:
[Training] → STOP → [Write to storage] → RESUME training
async_save:
[Training] → Fast copy to staging buffer → CONTINUE training immediately
↓
[Background upload to storage] ← happens while GPU computes
Real performance gains:
| Training Job | torch.save | async_save | Speedup |
|---|---|---|---|
| 2.8B param DDP, 32×H100 | 66s | 36s | 1.8× |
| 20B param FSDP, 32×H100 | 522s | 9s | 58× |
The training loop pays only for the staging copy, not the upload.
Now connect the pieces with a concrete example:
Scenario: Llama 3 training with ~8.6 interruptions per day
Checkpoint every 2 hours:
Expected waste per failure = 1 hour
Total daily waste = 8.6 × 1 hour = 8.6 hours
Goodput = (24 - 8.6) / 24 = 64%
Checkpoint every 30 minutes:
Expected waste per failure = 15 minutes
Total daily waste = 8.6 × 0.25 hours = 2.15 hours
Goodput = (24 - 2.15) / 24 = 91%
The math is simple:
Cutting checkpoint interval by 10× → cuts expected recovery time by 10×
async_save makes frequent checkpointing affordable because the GPU barely pauses.
Frequent checkpoints only help if recovery is automatic (no human intervention):
Job fails
↓
On restart: scan checkpoint directory
↓
Find most recent checkpoint WHERE .metadata file exists
↓ (skip any half-written checkpoints from the crash)
Load state → Resume training
The .metadata file acts as a commit marker — if it's there, the checkpoint is safe to use.
Even with perfect checkpointing, your GPUs can still sit idle — starved by a slow data pipeline.
❌ Bad pattern:
[Load batch] → [GPU computes] → [Load batch] → [GPU computes]
↑ ↑
GPU idle GPU idle
✅ Good pattern:
[Load batch N+1] overlaps with [GPU computes on batch N]
[Load batch N+2] overlaps with [GPU computes on batch N+1]
Impact: Customers switching to overlapping data loading see 20–50% decrease in wall-clock time.
On governed platforms, data lives in remote object storage (e.g., Unity Catalog volumes = network mounts).
Every batch access → Network request → Download file → Use it
↑
Slow! Repeated every epoch!
Epoch 1, first access:
File → Download from network → Cache to local NVMe → Use
Epoch 1+, subsequent access:
File → Read from local NVMe (fast!) → Use
Meanwhile: Pre-fetch upcoming files in background
Performance comparison (image classification, same GPU/model/batch):
| Metric | Stock PyTorch DataLoader | Optimized (UCVolumeDataset) |
|---|---|---|
| Epoch 1 throughput | 57.2 img/sec | 417 img/sec |
| Epoch 2 throughput | 371.6 img/sec | 6,590 img/sec |
| GPU utilization | 12.6% | 53.3% |
Epoch 2 is dramatically faster because the cache is warm — files are already on local NVMe.
Track the metric fetch_seconds — this measures how long the dataloader takes to produce a batch. During this time, your GPU is idle.
This is the most dangerous failure because it produces no error.
Training runs → Failure at step 5,000 (mid-epoch)
↓
Restore checkpoint: model ✓, optimizer ✓, step ✓
↓
Dataloader: starts from BEGINNING of dataset ✗
↓
Result: Re-trains on examples already seen, skips unseen examples
Why this is harmful:
Checkpoint = {
model weights,
optimizer state,
training step,
data position (sample/shard offset), ← often forgotten
RNG seeds and states ← often forgotten
}
Why RNG state matters: Shuffling and augmentation use random number generators. Without saving their state, the data order after restart won't match the order before — a saved position points at the wrong samples.
Here is the complete mental model:
Hardware failure occurs
↓
Auto-recovery finds last valid checkpoint (.metadata present)
↓
Restores: model + optimizer + step + data position + RNG state
↓
Training resumes with minimal lost work (small checkpoint interval)
↓
Data pipeline overlaps loading with compute (no GPU starvation)
↓
async_save checkpoints frequently with minimal GPU pause
↓
Repeat → High goodput maintained throughout
| Decision | Wrong Choice | Right Choice |
|---|---|---|
| Checkpoint method | torch.save on rank 0 | DCP with async_save |
| Checkpoint frequency | Once per day | Every 30 minutes (affordable with async) |
| Recovery | Manual human intervention | Automatic via .metadata marker |
| Data loading | Direct network reads every access | Local NVMe cache + prefetch |
| Data pipeline timing | Sequential (load then compute) | Overlapped (load during compute) |
| Checkpoint completeness | Model + optimizer only | + data position + RNG state |
Unifying principle: Frequent + inexpensive + complete checkpoints turn hardware failure from a catastrophe into a minor inconvenience. An overlapped data pipeline keeps GPUs busy in between.