feat: Phase 44 β multi-node distributed training - #51
Merged
aarambh-darshan merged 1 commit intoAug 16, 2026
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends v2 Β§27's single-node NCCL data parallelism to multiple nodes β
still data-parallel only, not model/pipeline-parallel β so training can scale
past whatever a single machine's GPU count offers. The gradient all-reduce
math is unchanged from v2; only the topology it runs over grows, and the
rendezvous that shares the NCCL unique id now supports a TCP transport so
nodes without a shared filesystem can join the world.
Bumps the workspace version to
4.0.0-alpha.4.Motivation
v2 Β§27 proved data-parallel training across the GPUs of one machine, but
its ceiling is the GPU count of a single box. Phase 44 lifts only that ceiling:
the world is now
N nodes Γ M GPUsinstead of1 node Γ M GPUs. Thegradient all-reduce math is byte-for-byte unchanged β what changes is the
topology it runs over and the rendezvous that bootstraps it.
Per the roadmap's honesty note, Kaggle notebooks do not provide genuine
multi-node access, so this phase is validated on CPU via a
distributedunit-test suite that exercises every multi-node code path (topology math,
TCP rendezvous over loopback, retry policy, rank-zero decision, device-count
fix) without needing CUDA hardware.
What changed
crates/aarambh-studio-train/src/distributed.rs(extended)MultiNodeTopologyβ combinesnum_nodes,gpus_per_node,node_rank, andlocal_rankinto the global rank and world size thatNCCL and the data loader see. Invariants:
world_size = num_nodes * gpus_per_noderank = node_rank * gpus_per_node + local_rankexactly the first node's first GPU, never every node's local rank zero.
RendezvousTransportenum (Filedefault |Tcp { endpoint }) βFilereproduces v2 single-node behaviour byte-for-byte;Tcp(Phase 44)lets genuinely separate nodes exchange the 128-byte NCCL unique id over
the network.
Rendezvoustrait +FileRendezvous+TcpRendezvousβ purestandard-library I/O that exchanges a
Vec<u8>blob, so the entirerendezvous layer compiles and is unit-tested on CPU without the
cudafeature. The actual NCCL
Idonly enters at the call site, behind#[cfg(feature = "cuda")].RetryPolicyβ exactly one retry on a transient (timeout /connection-refused) error, then fail loudly. Full elastic training is
explicitly out of scope.
device_count >= world_sizeon everyworker, which is wrong for multi-node (a 2-node Γ 2-GPU world has
world_size = 4but each node only has 2 GPUs). A multi-node worker nowneeds only
gpus_per_nodedevices locally; single-node runs keep v2's>= world_sizecheck byte-identical.DistributedConfiggains five fields βnum_nodes,node_rank,gpus_per_node,rendezvous,retry_attemptsβ all defaulting to thesingle-node v2 behaviour. Only
num_nodes >= 2activates multi-node mode.AARAMBH_STUDIO_NUM_NODES,AARAMBH_STUDIO_NODE_RANK,AARAMBH_STUDIO_GPUS_PER_NODE,AARAMBH_STUDIO_DIST_RENDEZVOUS_ENDPOINT,AARAMBH_STUDIO_DIST_RETRIES.crates/aarambh-studio-train/src/config.rsnum_nodes,gpus_per_node,node_rank, and the rendezvous transport when running multi-node.crates/aarambh-studio-train/src/lib.rsMultiNodeTopology,RendezvousTransport,Rendezvous,FileRendezvous,TcpRendezvous,RetryPolicy,NCCL_ID_BYTES,build_rendezvous).New files
configs/multinode_smoke.tomlβ CPU smoke config withnum_nodes = 2,gpus_per_node = 1, TCP rendezvous on loopback,retry_attempts = 1.scripts/phase44_smoke.shβ runs thedistributedunit tests, a CPUfallback training smoke, and writes a scorecard to
artifacts/phase44_multi_node_smoke.json.docs/phase44_multi_node.mdβ Phase 44 design, mechanism, CPU/CUDAhonesty policy, fault-tolerance scope, and test catalogue.
Docs / version bump
Cargo.tomlworkspace version β4.0.0-alpha.4;Cargo.lockregenerated.ROADMAP_V4.mdβ Phase 44 task checklist marked[x].CHANGELOG.mdβ[4.0.0-alpha.4]entry added.ARCHITECTURE_V4.mdΒ§58 β "Implementation (Phase 44)" subsection added.README.mdβ version, "Current Boundaries" (multi-node is data-parallelonly), phase-doc link, and citation version updated.
Backward compatibility
Every existing single-node config (e.g.
configs/wikitext103_small_2gpu.toml)deserialises to byte-identical v2 behaviour:
num_nodesdefaults to1, soworld_sizeandrankare taken as explicitly configured and the topologyis inactive. Only
num_nodes >= 2activates multi-node mode. The gradientall-reduce, bucketing, checkpoint format, and optimiser are all unchanged.
Tests
15 new/updated CPU unit tests in
aarambh-studio-train(nocudafeaturerequired), including the 4 roadmap-named acceptance tests:
world_size_one_node_reproduces_v2_single_node_behaviour_exactlygradient_all_reduce_correctness_across_simulated_multi_node_topologyrank_zero_checkpoint_writes_from_exactly_one_process_globallytransient_nccl_timeout_triggers_single_retry_then_fails_loudlymulti_node_topology_derives_global_rank_and_world_sizeinvalid_multi_node_topology_rejectedmulti_node_config_requires_gpus_per_node_devices_not_world_sizefile_rendezvous_round_trips_id_bytesfile_rendezvous_receive_times_out_when_rank0_never_publishestcp_rendezvous_broadcasts_id_bytes_across_loopbacksharded_data_loader_partitions_across_global_world_size_not_local_gpusmulti_node_topology_validate_requires_tcp_endpoint_when_configuredCI verification
All quality gates pass locally:
cargo fmt --all --checkβcargo check --workspace --all-targets --lockedβcargo clippy --workspace --all-targets --locked -- -D warnings -D clippy::undocumented_unsafe_blocksβcargo test --workspace --no-fail-fast --lockedβ (20 crates)RUSTDOCFLAGS="-D warnings -D missing_docs" cargo doc --workspace --no-depsβscripts/phase28_release_audit.sh(v4.0.0-alpha.4) β--version+ 29 subcommand--help) βscripts/phase44_smoke.shβ (checkpoint saved, 20 tensors)Out of scope (documented, not implied)
on node failure) β only the single-retry behaviour ships; the rest is
flagged as future work.
genuinely available, labelled with the validation path (external multi-VM
tunnel vs. single-machine loopback simulation).
Milestone