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. lend=True drops the copy-out without a buffer of your own, bounded at 4 live results.
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.1

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.1
File Size Uploaded
fast_ulysses-0.2.1.tar.gz 115.4 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for fast-ulysses 0.2.1
File
fast_ulysses-0.2.1-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.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
fast_ulysses-0.2.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
fast_ulysses-0.2.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details

Total release size: 1.5 MB

Release files / fast_ulysses-0.2.1.tar.gz

Download URL fast_ulysses-0.2.1.tar.gz
Size 115.4 kB
Tags Source
SHA-256 checksum
How to use checksums
eeeb73c5e1a5463df2fdcc121460684ecdc8ed443323b06c72389cfb0779b954
BLAKE2b-256 checksum
How to use checksums
fa3e99bcbf104a9a1dc708685b872d2ed16fb76dc87430b2cc6f62c7e5a2bf74
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 11, 2026.

Transparency log

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

Download URL fast_ulysses-0.2.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 340.4 kB
Tags CPython 3.13 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
372dc21f2090cef25ffa0937eb3b6b699d14f58a210d53616b5b4c1c4e623ef4
BLAKE2b-256 checksum
How to use checksums
bdab035a9aae95f071bf75ee71ea85a7eb27bfb09f1dc45dc3a7b9996cd45d58
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 11, 2026.

Transparency log

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

Download URL fast_ulysses-0.2.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 340.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
49d0469a02310dfbd94bd4fe5996b87924298a73399e832a5c574aaeeecad6bd
BLAKE2b-256 checksum
How to use checksums
8b7d1b139c36d3375629e6a4f3da3997543c04f58162575ee52e8d3893a7a411
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 11, 2026.

Transparency log

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

Download URL fast_ulysses-0.2.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 339.5 kB
Tags CPython 3.11 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
72dfd59233574040ec89e12c522aedf1533c78f6bd814c4458c0e540a9406613
BLAKE2b-256 checksum
How to use checksums
e625b4bce12572e7e0d5739f6bbb52f686b73735f41d70d82fb000f146f5386e
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 11, 2026.

Transparency log

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

Download URL fast_ulysses-0.2.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 337.8 kB
Tags CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
7d0970dc564ddf98a72271599790d7d0c2d5bfd9ddccf73b0898de229ad15650
BLAKE2b-256 checksum
How to use checksums
4f5140689a83e4dedaa75d9fe680b7b4531fc3acdfca8b52d2378dec80ecb15f
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 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

5 release files

0.2.0

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