Purlin
Purlin is a high-performance GPU communication framework for moving and reducing data across GPUs within a scale-up domain, such as an NVLink-connected server.
It provides both ready-to-use, single-kernel collectives and reusable device-side primitives for building custom communication and fusing it with computation.
Purlin includes AllReduce, AllGather, ReduceScatter, and AllToAll, plus variable-length variants of the latter three.
Underneath these collectives are two hardware-aware primitives: copy and N-to-1 reduce, which combines multiple input buffers into one output.
Key Idea
The key idea is decoupling orchestration from the datapath: separating where and when data moves from how the GPU moves it.
- Layouts describe the collective: how inputs and outputs are distributed, and whether to copy or reduce.
- SNAC coordinates execution: the shared Stage, Notify, And Consume (SNAC) protocol derives orchestration from those layouts.
- Atoms move the data: hardware-specific implementations perform the copies and reductions as coordinated by SNAC.
This separation makes Purlin evolvable:
- New hardware mechanisms can be added through Atoms without rewriting orchestration
- Communication is much easier to customize either at the collective level through our layouts or via composing our Atom building blocks.
Also, Purlin allows for extensive tuning (see codesign) to achieve peak performance.
🧨 QuickStart
uv pip install purlin # best to use a venv here
torchrun --nproc-per-node <num-of-gpus> quickstart.py
C++ benchmarks
Click here to see steps
Dependencies:
- CUDA Toolkit
- NVSHMEM (for C++ symmetric memory)
- MPI (to launch processes)
- CMake 3.27+
- Ninja
- CPM (for CMake dependency management)
Set NVSHMEM_LIB_HOME to your NVSHMEM library directory.
From the repository root:
export NVSHMEM_LIB_HOME=/path/to/nvshmem/lib
cmake -S csrc -B csrc/build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build csrc/build --target testAR testA2A testA2AV testAG testAGV testRS testRSV
| Collective | Binary |
|---|---|
| AllReduce | testAR |
| AllToAll / AllToAllV | testA2A / testA2AV |
| AllGather / AllGatherV | testAG / testAGV |
| ReduceScatter / ReduceScatterV | testRS / testRSV |
📏 Understanding
totalBytesThe reported
totalBytesis what we use to compute bandwidth. It is the output size for AllGather. For the other collectives, it is the input size per rank (also the output size for AllReduce and AlltoAll).
Run with one MPI process per GPU; for example, on 8 GPUs:
# each rank gets as input 1K...1G with output also the same size for the below
NVSHMEM_BOOTSTRAP=MPI NVSHMEM_REMOTE_TRANSPORT=none mpirun -n 8 ./csrc/build/testAR 1K 1G
# each rank gets as input: 128...128M but output is multiplied by world for allGather so 1K...1G
NVSHMEM_BOOTSTRAP=MPI NVSHMEM_REMOTE_TRANSPORT=none mpirun -n 8 ./csrc/build/testAG 128 128M
Arguments: [minBytes] [maxBytes] [graphLaunches] [runs] [warmup] [seed].
Atom implementations
| Atom | File |
|---|---|
Atom<700> |
fascia.cuh |
Atom<800> |
tendon.cuh |
Atom<900> |
ligament.cuh |
Atom<1000> |
cortex.cuh |
Reduction determinism
Enable deterministic mode for repeatable results with the same inputs and operator. All ranks must use the same mode.
C++:
purlin::allReduce<..., purlin::ReductionMode::deterministic>(src, dst, bytes, ctx, stream);
Python:
purlin.all_reduce(..., reduction_mode=purlin.ReductionMode.DETERMINISTIC)
The mode only changes the datapath on SM90 and newer: non-deterministic mode allows multimem, while deterministic mode disables it. On older GPUs (Ampere and below), both modes use the deterministic path.
Default is non-deterministic.
Release files for purlin 0.6.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| purlin-0.6.4.tar.gz | 18.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| purlin-0.6.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.5 kB
Release files / purlin-0.6.4.tar.gz
| Download URL | purlin-0.6.4.tar.gz |
|---|---|
| Size | 18.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d59ab9d4f17a6bf4eca84f42535ea14cd62429dbb41440f4009ab85b73123300
|
|
BLAKE2b-256 checksum How to use checksums |
9745a49c7c982f100434e910e22cf5a34c4f6bd8830cdab719ba965f0d39c46d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / purlin-0.6.4-py3-none-any.whl
| Download URL | purlin-0.6.4-py3-none-any.whl |
|---|---|
| Size | 13.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3f22c918829c0375014bd134a2eb9ebf1d6b4b2dd4f060aa6b594092febf2bed
|
|
BLAKE2b-256 checksum How to use checksums |
6dcb9d42bb826452249acefc916c5bbfc415253c79119b216a9a6a89fa2d7dbc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|