Skip to content

Commit 9d965db

Browse files
committed
feat: configure chunked Ulysses all-to-all
Add a ulysses_attention_chunks attention config to split the Ulysses all-to-all into head-group passes. The chunked path lets XLA overlap all-to-all collectives with head-parallel local attention compute while preserving the existing single-shot path by default. Apply the same chunking to plain Ulysses and Ulysses+Ring, and allow the final chunk to carry the remainder when the requested chunk count does not divide the Ulysses head groups evenly. Add mocked attention tests for numerical and layout equivalence across chunk counts.
1 parent d8ead5a commit 9d965db

18 files changed

Lines changed: 368 additions & 14 deletions

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,31 @@ To generate images, run the following command:
619619

620620
In our Wan2.2 I2V benchmarks at 40 inference steps, 81 frames, and `720x1280` resolution, Ulysses improved inference time by roughly `~10%` compared with flash attention, with about `~20s` lower latency on the v6e-8 and v7x-8 TPU setup.
621621

622+
#### Chunked Ulysses Attention (Overlapping Communication and Compute)
623+
624+
If you observe a major `all-to-all` communication bottleneck (especially when communication overhead is more pronounced compared to attention computation), you can enable **Chunked Ulysses Attention**.
625+
626+
By setting `ulysses_attention_chunks` greater than 1, MaxDiffusion splits the Ulysses all-to-all communication and attention computation into head-group passes (chunks). This allows XLA to overlap the all-to-all communication of one chunk with the head-parallel local attention compute of another chunk, significantly mitigating the communication bottleneck.
627+
628+
This chunking technique is supported and works for both plain Ulysses attention (`attention="ulysses"`) and hybrid Ulysses+Ring 2D attention/context parallelism (`attention="ulysses_ring"`).
629+
630+
To enable chunked Ulysses attention, set the corresponding override (e.g. `ulysses_attention_chunks=2` or `ulysses_attention_chunks=5`) in your config YAML or command line:
631+
632+
```bash
633+
python src/maxdiffusion/generate_wan.py \
634+
src/maxdiffusion/configs/base_wan_i2v_27b.yml \
635+
attention="ulysses" \
636+
ici_context_parallelism=4 \
637+
ulysses_attention_chunks=2 \
638+
...
639+
```
640+
641+
> [!IMPORTANT]
642+
> For communication-compute overlap to be effective on TPUs, you must enable the following XLA flags before running:
643+
> ```bash
644+
> export XLA_FLAGS="--xla_tpu_enable_async_all_to_all=true --xla_tpu_overlap_compute_collective_tc=true"
645+
> ```
646+
622647
### Caching Mechanisms
623648
624649
Wan 2.x pipelines support several caching strategies to accelerate inference by skipping redundant transformer forward passes. These are **mutually exclusive**enable only one at a time.

pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,19 @@ packages = ["src/maxdiffusion", "src/install_maxdiffusion_extra_deps"]
9292

9393
[tool.ruff]
9494
# Never enforce `E501` (line length violations).
95+
line-length = 119
96+
97+
[tool.ruff.lint]
9598
ignore = ["C901", "E501", "E741", "F402", "F823", "E402", "I001"]
9699
select = ["C", "E", "F", "I", "W"]
97-
line-length = 119
98100

99101
# Ignore import violations in all `__init__.py` files.
100-
[tool.ruff.per-file-ignores]
102+
[tool.ruff.lint.per-file-ignores]
101103
"__init__.py" = ["E402", "F401", "F403", "F811"]
102104
"src/maxdiffusion/utils/dummy_*.py" = ["F401"]
103105
"src/maxdiffusion/pyconfig.py" = ["E721"]
104106

105-
[tool.ruff.isort]
107+
[tool.ruff.lint.isort]
106108
lines-after-imports = 2
107109
known-first-party = ["maxdiffusion"]
108110

src/maxdiffusion/configs/base_wan_14b.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ use_base2_exp: True
8888
use_experimental_scheduler: True
8989
# For attention=ulysses_ring, hidden Ulysses shard count; ring shards are context / this.
9090
ulysses_shards: -1
91+
# Splits Ulysses all-to-all into head-group chunks. The last chunk carries any remainder.
92+
# For communication-compute overlap to be effective, enable the following XLA flags:
93+
# --xla_tpu_enable_async_all_to_all=true
94+
# --xla_tpu_overlap_compute_collective_tc=true
95+
# (Refer to README.md for the full recommended XLA_FLAGS list)
96+
ulysses_attention_chunks: 1
9197
flash_min_seq_length: 4096
9298
dropout: 0.0
9399

src/maxdiffusion/configs/base_wan_1_3b.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ use_base2_exp: True
8585
use_experimental_scheduler: True
8686
# For attention=ulysses_ring, hidden Ulysses shard count; ring shards are context / this.
8787
ulysses_shards: -1
88+
# Splits Ulysses all-to-all into head-group chunks. The last chunk carries any remainder.
89+
# For communication-compute overlap to be effective, enable the following XLA flags:
90+
# --xla_tpu_enable_async_all_to_all=true
91+
# --xla_tpu_overlap_compute_collective_tc=true
92+
# (Refer to README.md for the full recommended XLA_FLAGS list)
93+
ulysses_attention_chunks: 1
8894
flash_min_seq_length: 0
8995

9096
# If mask_padding_tokens is True, we pass in segment ids to splash attention to avoid attending to padding tokens.

src/maxdiffusion/configs/base_wan_27b.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ use_base2_exp: True
9494
use_experimental_scheduler: True
9595
# For attention=ulysses_ring, hidden Ulysses shard count; ring shards are context / this.
9696
ulysses_shards: -1
97+
# Splits Ulysses all-to-all into head-group chunks. The last chunk carries any remainder.
98+
# For communication-compute overlap to be effective, enable the following XLA flags:
99+
# --xla_tpu_enable_async_all_to_all=true
100+
# --xla_tpu_overlap_compute_collective_tc=true
101+
# (Refer to README.md for the full recommended XLA_FLAGS list)
102+
ulysses_attention_chunks: 1
97103
flash_min_seq_length: 4096
98104
dropout: 0.0
99105

src/maxdiffusion/configs/base_wan_animate.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ use_base2_exp: True
8686
use_experimental_scheduler: True
8787
# For attention=ulysses_ring, hidden Ulysses shard count; ring shards are context / this.
8888
ulysses_shards: -1
89+
# Splits Ulysses all-to-all into head-group chunks. The last chunk carries any remainder.
90+
# For communication-compute overlap to be effective, enable the following XLA flags:
91+
# --xla_tpu_enable_async_all_to_all=true
92+
# --xla_tpu_overlap_compute_collective_tc=true
93+
# (Refer to README.md for the full recommended XLA_FLAGS list)
94+
ulysses_attention_chunks: 1
8995
flash_min_seq_length: 4096
9096
# If mask_padding_tokens is True, we pass in segment ids to splash attention to avoid attending to padding tokens.
9197
# Else we do not pass in segment ids and on vpu bound hardware like trillium this is faster.

src/maxdiffusion/configs/base_wan_i2v_14b.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ use_base2_exp: True
8888
use_experimental_scheduler: True
8989
# For attention=ulysses_ring, hidden Ulysses shard count; ring shards are context / this.
9090
ulysses_shards: -1
91+
# Splits Ulysses all-to-all into head-group chunks. The last chunk carries any remainder.
92+
# For communication-compute overlap to be effective, enable the following XLA flags:
93+
# --xla_tpu_enable_async_all_to_all=true
94+
# --xla_tpu_overlap_compute_collective_tc=true
95+
# (Refer to README.md for the full recommended XLA_FLAGS list)
96+
ulysses_attention_chunks: 1
9197
flash_min_seq_length: 4096
9298
dropout: 0.0
9399

src/maxdiffusion/configs/base_wan_i2v_27b.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ use_base2_exp: True
8888
use_experimental_scheduler: True
8989
# For attention=ulysses_ring, hidden Ulysses shard count; ring shards are context / this.
9090
ulysses_shards: -1
91+
# Splits Ulysses all-to-all into head-group chunks. The last chunk carries any remainder.
92+
# For communication-compute overlap to be effective, enable the following XLA flags:
93+
# --xla_tpu_enable_async_all_to_all=true
94+
# --xla_tpu_overlap_compute_collective_tc=true
95+
# (Refer to README.md for the full recommended XLA_FLAGS list)
96+
ulysses_attention_chunks: 1
9197
flash_min_seq_length: 4096
9298
dropout: 0.0
9399

src/maxdiffusion/generate_wan.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ def inference_generate_video(config, pipeline, filename_prefix=""):
178178
negative_prompt = [config.negative_prompt] * config.global_batch_size_to_train_on
179179

180180
max_logging.log(
181-
f"Num steps: {config.num_inference_steps}, height: {config.height}, width: {config.width}, frames: {config.num_frames}, video: {filename_prefix}"
181+
f"Num steps: {config.num_inference_steps}, height: {config.height}, width: {config.width},"
182+
f" frames: {config.num_frames}, video: {filename_prefix}"
182183
)
183184

184185
videos = call_pipeline(config, pipeline, prompt, negative_prompt)

0 commit comments

Comments
 (0)