Configuring GPU Preemption Semantics and Fair-Share Quotas in AI Clusters
In high-density enterprise GPU clusters supporting multiple research, product, and platform engineering teams, uncoordinated resource scheduling leads to severe infrastructure gridlock. When competing teams submit large-scale distributed training jobs alongside latency-critical interactive fine-tuning sessions, primitive First-In, First-Out (FIFO) queue policies either strand valuable GPUs in idle states or allow long-running batch jobs to starve urgent production tasks for days. While workload preemption enables higher-priority jobs to reclaim hardware immediately, uncoordinated preemption enforcement creates catastrophic failure modes: standard Kubernetes or Slurm evaporative preemption terminates containers with hard SIGKILL signals, destroying hours of unsaved training progress, corrupting distributed model checkpoints, and leaving orphaned NCCL network socket bindings that require node reboots. Resolving this operational friction requires implementing graceful, hardware-aware preemption semantics coupled with hierarchical fair-share quota engines.
Prerequisites and Architecture: Graceful SIGTERM vs Hard SIGKILL Preemption

Hard SIGKILL signals terminate containers instantly, corrupting in-flight model weights, leaving unreleased NCCL network socket bindings, and wasting hours of compute. Designing an enterprise preemption architecture requires establishing strict protocol boundaries between cluster-level orchestration controllers and user-space deep learning frameworks. Without coordinated signal propagation, preempting a single worker in a distributed job triggers cascading cluster failures.
Failure Signatures of Uncoordinated Hard Preemption
When a scheduler abruptly evicts a GPU container using standard OS signals, two primary failure states emerge:
- Distributed Gang Deadlocks: In multi-node distributed training (such as PyTorch FSDP or Megatron-LM), all worker ranks are synchronized through collective communication rings. If the orchestrator evicts rank 14 while leaving the remaining ranks active, those remaining workers remain permanently blocked waiting for an AllReduce response until socket keepalive timeouts expire hours later.
- I/O Buffer Corruption: Abruptly severing PCIe and NVMe write streams during checkpoint serialization leaves fragmented tensor shards on disk. Upon subsequent job restart, the training framework encounters corrupt weights headers, invalidating training epochs.
To prevent these failures, the orchestration layer must grant a deterministic grace period (typically 60 to 90 seconds) following an initial SIGTERM notification, allowing user code to trap the signal, halt collective communicators gracefully, serialize an incremental weight snapshot, and exit cleanly:
Preemption Signal Flow Timeline:
T+00s: High-Priority Job Arrives -> Scheduler Issues Eviction to Low-Priority Pod
T+01s: Kubernetes sends SIGTERM to container main process PID 1
T+02s: PyTorch Signal Trap catches SIGTERM -> Broadcasts pause flag to all worker ranks
T+05s: Workers finish current mini-batch iteration -> Initiate TorchSnapshot flush
T+35s: Incremental checkpoint written to NVMe-oF storage -> Ranks close NCCL sockets
T+40s: Container exits cleanly with status 0 -> Scheduler immediately binds High-Priority Job
(If T > 90s: Orchestrator enforces SIGKILL as fallback timeout)
Step-by-Step Implementation: Configuring Priority Classes and Preemption Signal Traps
Define hierarchical PriorityClasses with calibrated termination grace periods, and implement a Python signal handler utilizing TorchSnapshot to write incremental state to shared storage before container exit. Deploying a production preemption pipeline requires configuring two interconnected layers: Kubernetes cluster PriorityClasses with calibrated termination grace periods, and a distributed Python signal trap handler integrated into the training loop.
1. Define Kubernetes Hierarchical Priority Classes
Create non-overlapping PriorityClass manifests that clearly distinguish between production serving, scheduled foundation model training, and preemptible exploratory experiments:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: ai-prod-critical
value: 1000000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "Mission-critical production inference and active customer-facing serving."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: ai-batch-preemptible
value: 10000
preemptionPolicy: Never
globalDefault: true
description: "Opportunistic batch training jobs that can be gracefully evicted at any time."
2. Implement the PyTorch Distributed Signal Trap Handler
In the distributed training entry point (e.g., train.py), register a signal handler that catches SIGTERM, sets a synchronized termination flag, and flushes incremental model state via torch_geometric or torchsnapshot:
import os
import signal
import sys
import torch
import torch.distributed as dist
import torchsnapshot
class GracefulPreemptionHandler:
def __init__(self, checkpoint_dir, model, optimizer):
self.checkpoint_dir = checkpoint_dir
self.model = model
self.optimizer = optimizer
self.preemption_requested = False
// Register signal handlers for both SIGTERM and SIGINT
signal.signal(signal.SIGTERM, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
def _signal_handler(self, signum, frame):
print(f"// Received signal {signum}. Initiating graceful distributed checkpoint...")
self.preemption_requested = True
def check_and_checkpoint(self, step_idx):
// Synchronize preemption state across all distributed ranks
flag_tensor = torch.tensor([1 if self.preemption_requested else 0], device="cuda")
dist.all_reduce(flag_tensor, op=dist.ReduceOp.MAX)
if flag_tensor.item() == 1:
if dist.get_rank() == 0:
print(f"// Flushed checkpoint at step {step_idx} due to scheduler preemption.")
snapshot = torchsnapshot.Snapshot.take(
path=os.path.join(self.checkpoint_dir, f"preempt_step_{step_idx}"),
app_state={"model": self.model, "optimizer": self.optimizer}
)
dist.barrier()
sys.exit(0)
3. Configure Automated Fair-Share Capacity Lending
On advanced multi-tenant AI platforms such as the OnePlus™ AI Orchestration Platform, resource managers enforce dynamic fair-share quotas natively. Teams are assigned guaranteed baseline GPU allocations (e.g., 64 GPUs). When Team A's cluster is idle, Team B can borrow those GPUs for low-priority batch jobs. However, the moment Team A submits a new workload, the OnePlus scheduler issues atomic preemption signals across Team B's borrowed instances, reclaiming the borrowed GPUs within the configured grace period (e.g., 60 seconds) without manual administrative intervention.
Verification Protocol: Auditing Preemption Latency and Recovery Time Objectives
Execute synthetic preemption injection drills measuring checkpoint serialization duration against grace period windows, and verify clean auto-restart from the latest checkpoint step. To validate that preemption functions flawlessly under heavy cluster concurrency, infrastructure teams must execute automated chaos-engineering drills.
Synthetic Preemption Drill and Telemetry Verification
Launch a 16-node distributed training job under the ai-batch-preemptible priority class. Once the job reaches steady-state iteration, submit an ai-prod-critical pod requesting the same GPU resources. Monitor cluster events and verify the following telemetry checkpoints:
- Signal Propagation Delay: Verify that
SIGTERMarrives at all 16 worker pods within 1.2 seconds of preemption scheduling. - Checkpoint Serialization Duration: Verify that the distributed state snapshot completes within 35 to 45 seconds over the high-speed storage fabric.
- Container Exit Status: Confirm that all worker pods terminate with exit code 0 rather than exit code 137 (SIGKILL).
- Job Restart Integrity: Re-launch the preemptible job against the newly written snapshot, verifying that model loss and optimizer momentum resume identically from the interrupted step.
Quantitative Preemption Telemetry Matrix
| Evaluation Metric | Graceful Preemption Target | Unmanaged Hard Preemption | OnePlus Platform Automated Baseline |
|---|---|---|---|
| Graceful Preemption Window | 60 to 90 seconds deterministic | 0 seconds (Immediate SIGKILL) | Configurable 60s window with auto-kill fallback |
| Distributed Checkpoint Success Rate | 100% verified state recovery | Frequent file header corruption | Graceful multi-rank signal and checkpoint coordination |
| Orphaned NCCL Sockets | Zero (clean TCP shutdown) | High (stale socket leaks requiring restart) | Automated socket cleanup and port verification |
| Cluster GPU Utilization | Sustained 85% to 92% | Depressed to 45% - 55% (fear of eviction) | 92%+ via dynamic fair-share capacity lending |
| Recovery Time Objective (RTO) | Under 90 seconds to resume | Hours lost due to manual triage | Automated queue re-queueing and fast-resume |
Frequently Asked Questions About GPU Preemption and Quotas
What is the recommended termination grace period for 70B parameter models?
For 70B parameter models, a grace period of 60 to 90 seconds is recommended when saving incremental optimizer states over a high-throughput NVMe-oF storage tier.
How does OnePlus Platform prevent GPU resource deadlocks during workload preemption?
OnePlus Platform features an atomic gang-scheduling engine that coordinates preemption signals across all distributed ranks simultaneously, granting a configurable grace window for distributed checkpointing and eliminating orphaned worker ranks.