Skip to main content

fast-ulysses

Ulysses sequence-parallel all-to-all as a torch custom op, moved by the GPU copy engines.

License

Ulysses sequence parallelism shards a long sequence across GPUs: one all-to-all before attention trades the sequence shard for a head shard, a second trades it back. For long-sequence video DiT workloads those two collectives are the critical communication.

This ships that 4D all-to-all as torch.ops.fast_ulysses.all_to_all_4d, over NVLink, on one node.

Key features

  • No SMs. The peer transfers are pitched cudaMemcpy2D/3DAsync straight into peers' symmetric-memory addresses, so they run on the copy engines while compute kernels hold every SM. (Measured: a peer copy overlaps a concurrent GEMM completely; a same-device copy does not, which is why out= from empty_output() — which removes the copy-out — is the faster path.)
  • Relayout for free. The sequence/head permutation is expressed as source and destination strides on those copies, not as two permute kernels. That is roughly half of what the torch.distributed path spends.
  • Uneven shards. Per-rank seq_splits / head_splits, which is what lets a caller drop sequence padding. Even splits are the special case, not a separate path.

Performance

8 GPUs, one exclusively allocated node per row, the same wheel and the same .so on all of them. base is torch.distributed permute + all_to_all_single + permute. Wan 720p, bf16, ms.

GPU fabric base ours vs base transfer of the fabric
H200 NVLink 1.569 0.860 1.82× 0.680 99%
B200 NVLink 1.194 0.550 2.17× 0.410 90%
B300 NVLink 1.184 0.548 2.16× 0.411 90%
H100 NVLink 1.616 0.971 1.66× 0.715 94%

47–60% of the baseline is relayout that costs nothing here. "Of the fabric" is the transfer against what a flat peer copy achieves on the same machine — at 90–99% there is nothing left to schedule. out= from empty_output() removes the copy-out for a further 1.14–1.28×.

Every number was taken twice, on two different nodes except H100, whose two samples are the same node. Full tables, per-stage timings and the method: docs/benchmark.md.

Quick start

Save this as example.py and run torchrun --nproc_per_node=8 example.py:

import os

import torch
import torch.distributed as dist
from fast_ulysses import UlyssesGroup

dist.init_process_group("nccl")
torch.cuda.set_device(int(os.environ["LOCAL_RANK"]))
group = UlyssesGroup()

b, s_local, heads, d = 1, 4096, 8, 128
ws = dist.get_world_size()
x = torch.randn(b, s_local, heads * ws, d, dtype=torch.bfloat16, device="cuda")

y = group.all_to_all_4d(x, mode=0)        # (b, s_local * ws, heads, d)
z = group.all_to_all_4d(y, mode=1)        # back to x's shape

group.destroy()
dist.destroy_process_group()

Every rank must issue the same sequence of shapes. More: docs/quickstart.md.

A real one — a DiT attention block, sequence-parallel, forward and backward, checked against the same block without sequence parallelism:

torchrun --nproc_per_node=8 examples/dit_attention.py

The collective is differentiable, so that block is an ordinary nn.Module: no autograd.Function wrapper, no manual backward.

API

Entry point Purpose
UlyssesGroup(process_group=None, device=None, *, require_nvlink=True) Collective. Refuses a group whose GPUs are not NVLink-joined.
group.all_to_all_4d(x, *, mode=0, out=None, seq_splits=None, head_splits=None) The collective. Returns a tensor the caller owns.
group.all_to_all_4d_async(x, *, ...) The same, on a comm stream, returning an AsyncCollectiveTensor.
group.empty_output(x, *, mode=0, ...) A symmetric buffer to pass as out=, which removes the copy-out. out= gives up the gradient.
group.destroy() Release the windows. Collective.
fast-ulysses doctor Build, devices, NVLink matrix.

Shapes, splits and the collective contract: docs/api.md. Why the code is shaped this way, and what it rests on that is not guaranteed: docs/design.md. Coming from DeepSpeed-Ulysses, sglang's usp.py or yunchang — what each call becomes, and what this does not have: docs/migration.md.

Limits

  • NVLink, one node, world_size in [1, 8], including odd sizes. Over PCIe — especially across a CPU socket — torch.distributed is faster, because the pitched copies this transport is built on degrade badly there. The constructor refuses such a group.
  • float16 / bfloat16 / float32 / float8_e4m3fn / float8_e5m2 / int8 / uint8, and d * elem_size must be 16-byte aligned — so d % 8 at bfloat16, d % 16 at float8.
  • Differentiable, and it propagates shapes under FakeTensor. Not traceable by torch.compile: the group is a torchbind object with no registered fake class, so Dynamo graph-breaks on it.
  • Forward-mode AD works — torch.autograd.forward_ad, torch.func.jvp, torch.func.linearize — at one extra collective for the tangent. Reverse-mode torch.func does not: grad / vjp / jacrev raise, and vmap raises by an explicit check, since it would run one collective per batch element and ranks that disagree on the batch size hang.
  • The async form is not differentiable and says so: its AsyncCollectiveTensor is a leaf, so a gradient would be dropped silently. Use all_to_all_4d when you need one.
  • out= is not differentiable either, and cannot say so: it reaches a mutating op with no autograd formula, so the result is the caller's buffer, detached. It is a speed knob for inference and no-grad regions, not for a training graph.
  • CUDA-graph capture covers the sync call on an already-warmed shape; see docs/design.md.

Install

Requires PyTorch 2.10+, CUDA 12.8+ or 13, and sm80 / sm90 / sm100 / sm120. torch is the only runtime dependency.

A wheel is built against one (torch minor, CUDA major) and embeds that torch's C++ ABI, so the pair has to match. Install torch first, then pick the index by the CUDA major it was built against:

pip install fast-ulysses --index-url https://triple-mu.github.io/fast-ulysses/whl/cu13/   # or cu12

That index carries fast-ulysses and nothing else, so pip cannot move your torch to satisfy it: it backtracks to the wheel pinned to the torch minor you already have. fast-ulysses wheel-url names the row for the environment running now and prints the same install as a fully pinned --find-links command against the release assets, when you want the file itself.

pip install fast-ulysses                                          # PyPI: torch 2.13.x + CUDA 13
pip install -e . --no-build-isolation                             # from source, all four arches
FAST_ULYSSES_CUDA_ARCH=90 pip install -e . --no-build-isolation   # one arch, much faster

PyPI carries that one pair, pinned torch==2.13.*. On any other torch the first command does not fail — pip upgrades torch to 2.13, a different CUDA build than the one you chose.

The one thing to know before reaching for --find-links: PEP 440 orders local versions, so an install that does not write +torch210cu128 out in full takes torch213cu130 whatever torch you have, silently. That, the per-row indexes and what to do when the import fails: docs/install.md.

Testing

pytest                  # the host-only plan tests always run; the GPU workers skip below 2 GPUs
pytest -m "not multigpu"                                   # host-only, no GPU needed
torchrun --nproc_per_node=8 test/distributed/correctness.py

Development setup: docs/develop.md.

License

Apache-2.0. See LICENSE.

Metadata

Release files for fast-ulysses 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fast-ulysses 0.2.0
File Size Uploaded
fast_ulysses-0.2.0.tar.gz 110.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for fast-ulysses 0.2.0
File
fast_ulysses-0.2.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
fast_ulysses-0.2.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details
fast_ulysses-0.2.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details
fast_ulysses-0.2.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 Details

Total release size: 1.5 MB

Release files / fast_ulysses-0.2.0.tar.gz

Download URL fast_ulysses-0.2.0.tar.gz
Size 110.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ca73f428de60c93c4f1a6900b31f5820501fd4e038fa41f18766eb7bf6b50363
BLAKE2b-256 checksum
How to use checksums
a97f78b4e2f372fbe0a2e03ae61e6a6ade116dd190d8da41f957ee3ef5e91ace
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release files / fast_ulysses-0.2.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL fast_ulysses-0.2.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 336.3 kB
Tags CPython 3.13 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
7b464c09963c98703bc9478a46fdc7ef9ef9c3878e751b7447cb8928b15a030c
BLAKE2b-256 checksum
How to use checksums
a012bf45b10217edb31d0545d76658bc6d7c6686ed6e740e68ca5746e7344e7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release files / fast_ulysses-0.2.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL fast_ulysses-0.2.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 336.3 kB
Tags CPython 3.12 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d6e42784b68392c0e6b391c21c6fe7c668c714b405d6248aa09e7b5865e4be18
BLAKE2b-256 checksum
How to use checksums
9410f93cb777b757d7a081cb3cdccaba1587831eab9e87d61f5f6fd061fe2045
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release files / fast_ulysses-0.2.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL fast_ulysses-0.2.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 335.4 kB
Tags CPython 3.11 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
9c34d2fccedc74a8b208c184a97be4ac6b79aa9dc865b8447aa35d3ddc5f451a
BLAKE2b-256 checksum
How to use checksums
308024a591cbc2c096d0bf297c28774c5c3f1de31995cb3cbb019e5eb24b457f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release files / fast_ulysses-0.2.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL fast_ulysses-0.2.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 334.1 kB
Tags CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
5a10f4d0f436c720c165c5405fc776289f67ee3e8c7b6a7d642f01e8985aaf2d
BLAKE2b-256 checksum
How to use checksums
1224c8fe5bc601d5bc0c6cac9e3d684b2128f803c4c6ae4de3ec27ef5b55e865
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.1

5 release files

This release

0.2.0 This release

5 release files

0.1.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page