tandem · distributed training from scratch
The parallelisms behind large-model training, on PyTorch tensors and autograd but with no torch.distributed and no NCCL: its own ring all-reduce, reduce-scatter and all-gather underneath DDP, ZeRO-1, 2 and 3, and GPipe and 1F1B pipelines. On two T4 GPUs every one ends with exactly PyTorch's weights.
bench/run.py verify on two Tesla T4s: after 20 training steps, every mode ends with the same losses and weights as PyTorch.
| tandem mode | Checked against | Weights |
|---|---|---|
| DDP | torch DDP (NCCL) | equal |
| ZeRO-1 | torch DDP (NCCL) | equal |
| ZeRO-2 | torch DDP (NCCL) | equal |
| ZeRO-3 (FSDP-style) | torch DDP (NCCL) | equal |
| Pipeline, 1F1B | one process | equal |
torch FSDP matches torch DDP too, so ZeRO-3 is equal to both.
The collectives moved into a PyTorch C++ extension: lock-free single-producer, single-consumer rings in shared memory and a progress thread on the CPU; on GPUs, buffers shared through CUDA IPC, ordered by interprocess events and reduced by a fused CUDA kernel, so the host never waits for a piece.
| All-reduce on a Tesla T4 | Python engine | C++ engine | Speed-up |
|---|---|---|---|
| 64 KB | 1.79 ms | 0.64 ms | 2.8× |
| 1 MB | 1.53 ms | 0.83 ms | 1.9× |
| 4 MB | 1.65 ms | 0.75 ms | 2.2× |
| 64 MB | 10.00 ms | 6.24 ms | 1.6× |
Results bit-identical between the two engines.
Each parallelism is built on the same three collectives, in the order Megatron-LM and FSDP use them.
Gradient buckets reduced as backward fills them, so communication hides behind compute.
Sharded optimizer state, gradients and, FSDP-style, parameters gathered just before use and prefetched: 17% less memory per GPU than DDP.
Pipeline schedules in Megatron-LM's order; 1F1B uses 32–52% less memory than GPipe on an 86M-parameter GPT.
What torch.distributed, NCCL, DeepSpeed and Megatron do, rebuilt so that every byte on the wire is accounted for.
Ring all-reduce, reduce-scatter and all-gather within 2% of NCCL's bandwidth at 64–256 MB.
DDP, ZeRO-1/2/3 and GPipe/1F1B, bit-identical to PyTorch after 20 steps.
Shared-memory rings, CUDA IPC and a fused reduce kernel: 1.6–2.8× faster.
ZeRO-3 17% less than DDP; 1F1B 32–52% less than GPipe.
tandem's DDP reaches 86% of PyTorch DDP's throughput, and the C++ engine has not yet been timed against NCCL across two GPUs.
@software{kundu2026tandem,
author = {Kundu, Sankur},
title = {tandem: distributed training on its own collectives},
year = {2026},
url = {https://github.com/Shakhtar-Sankur/tandem},
license = {Apache-2.0}
}