gpu_count. What you do with them is one of two shapes, and both are one line.
Many trainings, one card each
One training, many cards
distributed.run starts one process per card the container was given, gives each its rank, joins them
into a process group, calls your function on every rank and returns what rank 0 returned. Change
gpu_count to 2 or 8 and nothing else changes. With gpu_count=1 there is nothing to spawn: the function
runs in place and every helper answers as a world of one, so one function covers 1x, 2x, 4x and 8x.
Inside the function, the helpers are the handful a loop needs:
dist.shard(rows) gives a rank its slice of a list when a static split is simpler than indexing.
The function must be a module-level function (ranks are separate processes and import it by name), and
everything it needs goes in through its arguments.
A step trains
world_size examples instead of one, so an effective batch of 32 on four cards is 8 per
card; adjust gradient accumulation accordingly if a run is meant to be comparable to a single-card one.torchrun and accelerate
Undertorchrun or accelerate launch the process is already a rank. distributed.run notices, joins the
group and calls the function; the helpers read the same RANK / WORLD_SIZE / LOCAL_RANK those launchers
set. Code written for them keeps working.
What the cards need
Cards have quirks, and they live inlevers9.distributed rather than in every training script.
Anything you set yourself wins over these defaults.
Sizing, measured
On four RTX PRO 6000s in one node, the same 10,170-step fine-tune:
3.15x on four cards is what NCCL through shared memory costs. Four single-card cells, when the work is
independent, get the full 4x, which is why the sweep shape comes first above.
What a multi-card job waits for
A multi-card job needs one worker holding that many cards, so it waits for a node with that many free at the same moment. On an attached cluster the agent reports what each node has free; a node whose other cards belong to another deployment offers only what is left. To borrow a whole node, scale the neighbour down and the job starts as soon as the cards show as free. Two limits gate more than one card per job: the controlplane’s per-stub cap (stubLimits.maxGpuCount,
raised to 8 on the hosted deployment) and the workspace’s own switch:

