ADR-0007: Distributed launch and rendezvous
- Status: Accepted (milestone 1) for torchrun static rendezvous, validated multi-process on one host. Multi-machine operation is Proposed (not validated).
- Date: 2026-10-29
Context
A distributed job is one logical workload across several nodes and processes. GPUlayer should own allocation, rank assignment, rendezvous configuration and lifecycle. It should not own collective communication, which PyTorch already provides.
Decision
DistributedJob(contracts/models.py) declaresnum_workers,procs_per_worker,launcher="torchrun",comm_backend(glooornccl;ncclrequires CUDA), theentrypointscript inside the source bundle, andrendezvous(static, optional port, join timeout).failure_policyisfail_fast.- Allocation: gang scheduling of a compatible worker group (ADR-0004). One task is
created per node with
node_rank0..N-1.plan_group(runtime/distributed.py) defines the global rank layout: node r hosts ranks [r·P, (r+1)·P). - Rendezvous: when the rank-0 worker acquires its task, it picks the port (from the
spec, or a free one) and publishes
advertise_address:portthroughpublish_rendezvous. The control plane withholds rank>0 assignments until that endpoint exists. Only node rank 0 may publish, and a conflicting re-publish is rejected. - Launch: each worker runs
python -m torch.distributed.run --nnodes N --nproc-per-node P --node-rank r --master-addr A --master-port p --max-restarts=0 <entrypoint>(torchrun_argv) in its own process group. The script readsGPULAYER_COMM_BACKENDand callsinit_process_group. - Coordination: the job succeeds only when every node succeeds. When any node
fails, is lost or times out, the job fails immediately, and running siblings get
cancel_requested(delivered by heartbeat) while unstarted ones are cancelled. Distributed jobs are never retried automatically (JobSpecvalidation rejectsmax_attempts>1). - Logs are tagged with
node_rank. Outputs are uploaded per node undernode<r>/.
Validation
tests/distributed/test_torchrun_multiprocess.pyruns two worker agents as two "nodes" on a single host, each launching torchrun with 2 processes (world size 4), and verifies a glooall_reduce. A second test shows that one failing rank fails the whole job and stops the sibling.- Not validated: separate machines, real networks, firewalls and interface selection, NCCL, or CUDA multi-GPU. Single-host loopback does not establish multi-node support.
Alternatives considered
- c10d/etcd elastic rendezvous: supports elasticity, but it is not needed for
fail-fast semantics. It remains a later option behind the same
RendezvousSpec. - A custom collective layer: forbidden by CLAUDE.md.
- Ray Train or DeepSpeed launchers: possible additional
launchervalues later.
Consequences and trade-offs
- Rank-0's advertised address must be reachable from every peer. GPUlayer does not verify reachability before launch, so failures surface as torchrun rendezvous timeouts.
free_port()has a small race: the port could be taken before torchrun binds it.- Partial execution can leave side effects such as checkpoints. There is no checkpoint/restart support.
Security and operational implications
- The rendezvous port is unauthenticated (a torch limitation). Run distributed jobs only on trusted private networks.
Follow-up
- A multi-machine validation environment (two hosts, documented network) and a test.
- A reachability pre-check, NCCL/CUDA validation, and an explicit network-interface selection option.
- Checkpoint-aware restart as an opt-in policy.