Fractional & Multi-GPU Scheduling¶
You ask for VRAM (vram="10GB"), not "a GPU" — and the gateway figures out how to place it. This note is how that placement works; for the SDK surface see client_sdk, for the wider scheduler see job_gateway.
The problem¶
Ray reports how many whole GPUs a node has, not how much VRAM is free on each one. That's not enough to safely pack a 10 GB job next to a 60 GB job on the same 80 GB card. So the gateway keeps its own VRAM ledger (vram_ledger.py) — an in-memory, per-GPU account of who's using how much, built from Ray's per-GPU custom resources (VRAM_MB_GPU0, VRAM_MB_GPU1, … from gpu_support) and kept restart-safe by rehydrating from the job/endpoint CRDs.
The placement rule¶
Given a VRAM request, the ledger:
- Fits on one GPU → fractional. It reserves a slice and hands Ray a fractional
num_gpus(10 GB of an 80 GB card ≈0.125), so several small jobs share one physical GPU. - Bigger than any single GPU → multi-GPU. It reserves N whole GPUs on the same node and sets
CUDA_VISIBLE_DEVICESto them (100 GB → 2× 80 GB). - Best-fit. Among the GPUs that fit, it picks the tightest one first — leaving the big, empty GPUs free for the jobs that actually need them.
- Vendor + mixed cards. Preference is NVIDIA → AMD → Apple; and because each GPU is tracked on its own, a node with a 24 GB 4090 next to an 80 GB A100 just works.
VRAM is released when the job or endpoint finishes (or fails). The same ledger backs jobs, training, and endpoints.