mirror of
https://github.com/huggingface/diffusers.git
synced 2026-10-24 20:59:27 +03:00
* draft:add neuron as a legit backend
* feat: neuron-specific changes in the pipeline
* tests: eager tests
* draft: start with tp for flux2
* fix: style
* fix:apr_02 beta
* feat:add wan
* fix:pixart
* fix: rewrite flux swiglu activation to avoid gather op in neuron IR
* test: pixart compile mode on neuron
* cleanup & fix style
* merge: another change
* review: cleanup+suggestions
* fix: CIs style
* tests: add test units for tp
* fix: in case of text-encoder(s) on CPU
* review:cleanup+add test
* fix: style
* doc: remove it for now
* Add from_single_file support for SkyReelsV2 and ChronoEdit transformers (#13946)
SkyReels-V2 and ChronoEdit are both built on Wan, and their transformers have
the same keys as WanTransformer3DModel, so they reuse
convert_wan_transformer_to_diffusers (like WanVACE / WanAnimate). This lets the
community GGUF builds load directly.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* multi-GPU VAE Fix for Cosmos 3 (#13924)
fix(cosmos3): pin VAE latent norm buffers to encode output device
Under sharded placement (device_map="balanced"), vae.encode() runs on the
VAE's own device while the mean/inv_std buffers were pinned to x.device,
causing a cross-device RuntimeError. Compute raw_mu first, then pin the
normalization buffers to its device so all tensors share one device.
Co-authored-by: Atharva Joshi <atjoshi@smc521ge-0036.ipp2a2.colossus.nvidia.com>
Co-authored-by: Sayak Paul <spsayakpaul@gmail.com>
* docs: fix repeated word typo in set_timesteps docstring (#13876)
* docs: fix repeated word typo in set_timesteps docstring
Removed the duplicate word "schedule" from the docstring for the sigmas argument in EulerDiscreteScheduler.set_timesteps.
* Update scheduling_euler_discrete.py
* Apply style fixes
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* clean some stuff to simplify code.
* clean more to remove permutation related shenanigans.
* revert: put torch.chunk back
* Update docs/source/en/training/distributed_inference.md
Co-authored-by: Sayak Paul <spsayakpaul@gmail.com>
* Address Sayak's TP review nits (docstrings + stale comments)
- _modeling_parallel: fix stale comment claiming attention processors read
tp_degree at runtime (no longer true after the PackedColwise/Rowwise
refactor; processors are TP-agnostic via head_dim).
- tensor_parallel: single backticks instead of double in docstrings, add
input/output examples to _blocks_to_block_sizes and _resolve_tp_plan, and
drop the stale "applies the Flux2 fused-weight permutations" line from
apply_tensor_parallel (permuters were removed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Fix stale permuter reference in Flux2ParallelSelfAttnProcessor comment
The proportional QKV/MLP slice is now guaranteed by PackedColwiseParallel
block-by-block sharding, not the removed fused-weight permuter.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Derive TP backend inside apply_tensor_parallel from the mesh device type
Drops the `backend` parameter: apply_tensor_parallel already holds the TP
mesh, so it derives neuron-vs-default from `config._mesh.device_type` itself.
The caller no longer computes it. Documents why torch_device can't be used
(Neuron reports as "cpu" via torch's accelerator API). Removes the now-unused
is_torch_neuronx_available import from modeling_utils.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Simplify TP backend derivation to the mesh device type alone
Drop the redundant is_torch_neuronx_available() guard: a DeviceMesh("neuron", ...)
only exists when running on Neuron, so tp_mesh.device_type is the single source
of truth.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Remove incorrect "Neuron reports as cpu" rationale from TP backend docstring
Verified on the current native torch_neuronx drop that Neuron does surface as
the torch accelerator (torch._C._get_accelerator().type == "neuron",
get_device() == "neuron"); the old "reports as cpu" claim was stale. The
mesh-device-type derivation is unchanged — it's the device being sharded onto.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Drop stale "XLA" labels from Neuron device/runtime comments
Neuron is a native torch backend now (not XLA-routed): remove the "(XLA)"
parenthetical from the randn-on-CPU note in torch_utils and the "XLA runtime"
mention from the Neuron TP test docstring. Behavior unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* make style: reflow tensor_parallel docstrings
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Revert "revert: put torch.chunk back"
This reverts commit 7ea75f771a.
* fix: sharding for neuron + validate flux 1
* fix: change for check_repository_consistency
* feat: support qwen image as well
* Update docs/source/en/training/distributed_inference.md
Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
* review: keep bria and nucleusmoe out
* review: keep bria and nucleusmoe out
* review: keep bria and nucleusmoe out
* review: address agent review
* review: apply suggestions
* Update docs/source/en/training/distributed_inference.md
Co-authored-by: Sayak Paul <spsayakpaul@gmail.com>
* review: change example tp size to 4
* review: add flux tp test
* review: address comments
* review: improve the doc
* review:apply qwen rotary_emb per device
* review:remove redundant device def after PR #14383
* review: doc title suggestion
* review: restore copy comment
* review: remove cp divisibility explanation from doc on parallelism guide
* fix style
---------
Co-authored-by: Hz_Zhang <47402297+HaozheZhang6@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Atharva Joshi <atjoshi@nvidia.com>
Co-authored-by: Atharva Joshi <atjoshi@smc521ge-0036.ipp2a2.colossus.nvidia.com>
Co-authored-by: Sayak Paul <spsayakpaul@gmail.com>
Co-authored-by: Ramkumar R <ramkumarashvanth09@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Steven Liu <59462357+stevhliu@users.noreply.github.com>
112 lines
4.8 KiB
Python
112 lines
4.8 KiB
Python
# coding=utf-8
|
|
# Copyright 2026 HuggingFace Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Generic torchrun worker: assert a model's Neuron tensor-parallel output matches its single-device reference.
|
|
|
|
Model-agnostic. The model under test is supplied as a `module:function` spec reference on the command line; the
|
|
referenced factory returns `(model_class, init_dict, inputs)` with CPU tensors, so all model-specific test data lives
|
|
with the launching test rather than here.
|
|
|
|
Launched as a subprocess by a `@require_torch_neuron` test (and runnable directly for debugging)::
|
|
|
|
torchrun --nproc_per_node=2 _neuron_tp_worker.py \\
|
|
tests.models.transformers.test_models_transformer_flux2:make_neuron_tp_spec
|
|
|
|
Each rank builds an identical (seeded) model on CPU, computes a single-device reference, then shards it with
|
|
`enable_parallelism(TensorParallelConfig(mesh=neuron_mesh))` — which auto-selects the Neuron pre-shard backend — runs
|
|
a forward pass on the Neuron device, and asserts the gathered output matches the reference. Exit code 0 means the TP
|
|
path is numerically equivalent to the unsharded model; non-zero means failure.
|
|
"""
|
|
|
|
import argparse
|
|
import importlib
|
|
import os
|
|
import sys
|
|
import traceback
|
|
|
|
|
|
# Make the in-repo `diffusers` and `tests` packages importable when run via torchrun from an arbitrary CWD.
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "src"))
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
|
|
|
import torch
|
|
import torch.distributed as dist
|
|
import torch_neuronx # noqa: F401 — registers torch.neuron
|
|
from torch.distributed.device_mesh import DeviceMesh
|
|
|
|
from diffusers import TensorParallelConfig
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Neuron tensor-parallel correctness worker.")
|
|
parser.add_argument(
|
|
"spec",
|
|
help="`module:function` reference returning (model_class, init_dict, cpu_inputs) for the model under test.",
|
|
)
|
|
args = parser.parse_args()
|
|
module_name, _, fn_name = args.spec.partition(":")
|
|
model_class, init_dict, inputs = getattr(importlib.import_module(module_name), fn_name)()
|
|
|
|
dist.init_process_group(backend="neuron")
|
|
rank = dist.get_rank()
|
|
tp_size = dist.get_world_size()
|
|
device = torch.neuron.current_device()
|
|
tp_mesh = DeviceMesh("neuron", list(range(tp_size)))
|
|
|
|
# Identical weights on every rank (same seed), kept on CPU as the Neuron pre-shard backend requires.
|
|
torch.manual_seed(0)
|
|
model = model_class(**init_dict).eval()
|
|
|
|
# Single-device (unsharded) reference on CPU, computed before TP mutates the weights in place.
|
|
with torch.no_grad():
|
|
ref_output = model(**inputs, return_dict=False)[0].float().cpu()
|
|
|
|
# Shard across all ranks; the Neuron backend is auto-selected from the mesh device type.
|
|
model.enable_parallelism(config=TensorParallelConfig(mesh=tp_mesh))
|
|
model = model.to(device)
|
|
torch.neuron.synchronize()
|
|
|
|
inputs_on_device = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in inputs.items()}
|
|
with torch.no_grad():
|
|
tp_output = model(**inputs_on_device, return_dict=False)[0]
|
|
torch.neuron.synchronize()
|
|
tp_output = tp_output.float().cpu()
|
|
|
|
if rank == 0:
|
|
assert tp_output.shape == ref_output.shape, f"shape mismatch: {tp_output.shape} vs {ref_output.shape}"
|
|
assert torch.isfinite(tp_output).all(), "TP output contains non-finite values"
|
|
max_abs = (tp_output - ref_output).abs().max().item()
|
|
denom = ref_output.abs().max().item() + 1e-6
|
|
print(
|
|
f"[rank0] tp_size={tp_size} output_shape={tuple(tp_output.shape)} "
|
|
f"max_abs_diff={max_abs:.4e} max_rel_diff={max_abs / denom:.4e}"
|
|
)
|
|
# Neuron runs matmuls in bf16 internally, so compare with a bf16-level tolerance. A wrong shard
|
|
# plan produces grossly different output and is caught comfortably within this bound.
|
|
torch.testing.assert_close(tp_output, ref_output, atol=2e-2, rtol=2e-2)
|
|
print("[rank0] PASS: Neuron tensor-parallel output matches single-device reference.")
|
|
|
|
dist.barrier()
|
|
dist.destroy_process_group()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except Exception:
|
|
traceback.print_exc()
|
|
# Ensure a non-zero exit so the launching pytest sees the failure.
|
|
os._exit(1)
|