kempnerforge.resilience¶
Fault tolerance and resilience for KempnerForge.
- class kempnerforge.resilience.NaNDetector[source]¶
Bases:
objectDetects and tracks NaN/Inf values in loss and gradients.
- Supports three responses to NaN:
"warn": Log a warning and continue."skip": Skip the optimizer step (zero gradients)."raise": Raise aRuntimeError.
Once the consecutive NaN count reaches
max_consecutive, the detector signals that a checkpoint rollback is recommended.- Parameters:
action – What to do when NaN is detected.
max_consecutive – Consecutive NaN steps before recommending rollback.
max_history – Number of NaN step indices to retain.
- check_loss(loss, step, grad_norm=None)[source]¶
Check a step’s loss, and its gradient norm when given, for NaN/Inf.
When running distributed, all-reduces a NaN flag so ALL ranks agree on whether to skip. Prevents rank desync where one rank sees NaN and skips its optimizer step while others proceed normally.
A finite loss does not guarantee finite gradients: a micro-batch whose labels are all masked has an exact zero cross-entropy loss whatever its activations, so the caller passes the gradient norm as well. Each rank’s norm goes into the same reduced flag as the loss, so every rank skips the step together even when a non-finite gradient reaches only some ranks’ norms.
- Parameters:
- Returns:
True if the loss and the gradient norm are finite on ALL ranks, False if any rank has NaN/Inf in either.
- Raises:
RuntimeError – If action is “raise” and NaN is detected.
- Return type:
- check_gradients(model, step)[source]¶
Check model gradients for NaN/Inf before optimizer step.
- Parameters:
model (torch.nn.Module) – The model to check.
step (int) – Current training step.
- Returns:
True if all gradients are finite.
- Return type:
- class kempnerforge.resilience.NaNState[source]¶
Bases:
objectTracks NaN/Inf occurrences across training steps.
- class kempnerforge.resilience.SLURMInfo[source]¶
Bases:
objectInformation about the current SLURM job.
- class kempnerforge.resilience.ShutdownHandler[source]¶
Bases:
objectCooperative shutdown handler for long-running training jobs.
Register this handler before the training loop. The training loop checks
should_shutdown()after each step and takes appropriate action (save checkpoint, clean up, exit).If the graceful shutdown exceeds
timeout_sec, a forced exit is triggered viaos._exitto avoid hanging on stuck collectives.Usage:
handler = ShutdownHandler(timeout_sec=120) handler.register() for step in range(max_steps): train_step() if handler.should_shutdown(): save_checkpoint() handler.finish() break
- Parameters:
timeout_sec – Maximum seconds allowed for graceful shutdown before forced exit. Set to 0 to disable the timeout.
- should_shutdown()[source]¶
Check if the training loop should exit.
Call this after each training step.
- Return type:
- kempnerforge.resilience.check_gpu_health(device=0)[source]¶
Run basic GPU health checks.
- Performs:
CUDA availability check
Small test computation on the device
Memory allocation test
- kempnerforge.resilience.check_nccl_health(timeout_sec=10.0)[source]¶
Check NCCL communication health via a lightweight all-reduce.
The all-reduce runs with
async_op=Truesowork.wait(timeout=...)enforces the caller’s bound rather than falling back to the process-group default timeout (nccl_timeout_sec, 1800s). Without that, this function would sit for 30 minutes on a single stuck peer regardless of thetimeout_secargument.
- kempnerforge.resilience.get_slurm_info()[source]¶
Read SLURM job information from environment variables.
- Returns:
SLURMInfo if running under SLURM, None otherwise.
- Return type:
SLURMInfo | None
- kempnerforge.resilience.is_slurm_requeue()[source]¶
Check if this is a requeued SLURM job.
Uses
SLURM_RESTART_COUNT(set by SLURM on requeue).- Return type:
- kempnerforge.resilience.log_job_info()[source]¶
Log SLURM job information (if running under SLURM).
- Return type:
None
- kempnerforge.resilience.resolve_resume_path(checkpoint_dir, num_stages=None, *, require_train_state=True)[source]¶
Find the latest checkpoint for auto-resume.
- Checks:
{checkpoint_dir}/latestsymlinkMost recent
step_Ndirectory whose save completed
CheckpointManageronly ever pointslatestat a complete checkpoint, so (1) needs no further test; one that lost files since is returned as is, and the load reports it. Thestep_Nfallback has no such guarantee: an interrupted save leaves a directory that exists but holds no.metadata, and resuming into it fails indcp.loadwith “metadata is None”. A save that stopped after its DCP shards and beforetrain_state.ptleaves optimizer state without the step, LR schedule and data position that go with it, whichCheckpointManager.loadrefuses. Skipping both kinds turns an unrecoverable run into one that resumes from the last complete checkpoint, whatever left the partial directory behind. Whenstep_Ndirectories exist but none is complete, a run that meant to resume starts over, so that is logged at ERROR.- Parameters:
checkpoint_dir (str) – Base checkpoint directory.
num_stages (int | None) – The run’s pipeline degree. With it, a
step_Nin the per-stage layout counts only whenpp0throughpp{num_stages - 1}all hold.metadata, including stages that never created their directory; see_dcp_durable. When no step has every stage, the newest one that is otherwise complete is returned as before, after an error log, rather than the run starting over: a checkpoint saved with another pipeline degree looks the same, and resume does not support changing the degree.require_train_state (bool) – Skip a
step_Nwhose shards hold optimizer state but that has notrain_state.pt. A caller that loads the weights alone, which such a checkpoint still holds in full, passes False to keep the newest one.
- Returns:
Path to the latest usable checkpoint, or None if none found.
- Return type:
Path | None
Modules
Elastic training and SLURM integration helpers. |
|
GPU health monitoring and NaN detection. |
|
Graceful shutdown via signal handling. |