94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
182 lines
6.4 KiB
Python
182 lines
6.4 KiB
Python
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
from typing import TYPE_CHECKING, Callable
|
|
|
|
import torch
|
|
|
|
from sglang.multimodal_gen.runtime.distributed import get_local_torch_device
|
|
from sglang.multimodal_gen.runtime.distributed.cfg_policy import (
|
|
_apply_cfg_postprocess,
|
|
_unwrap,
|
|
_wrap,
|
|
)
|
|
from sglang.multimodal_gen.runtime.distributed.communication_op import (
|
|
cfg_model_parallel_all_gather,
|
|
cfg_model_parallel_all_reduce,
|
|
)
|
|
from sglang.multimodal_gen.runtime.distributed.parallel_state import (
|
|
get_cfg_group,
|
|
get_classifier_free_guidance_rank,
|
|
get_classifier_free_guidance_world_size,
|
|
)
|
|
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
|
|
|
logger = init_logger(__name__)
|
|
|
|
if TYPE_CHECKING:
|
|
from sglang.multimodal_gen.runtime.distributed.cfg_policy import (
|
|
CFGBranch,
|
|
CFGPolicy,
|
|
)
|
|
|
|
# Tracks (n_branches, cfg_world_size, cfg_rank) tuples already logged so the
|
|
# dispatch table is printed once per unique configuration, not once per step.
|
|
_logged_dispatch_keys: set[tuple[int, int, int]] = set()
|
|
|
|
|
|
def _run(
|
|
predict_fn: Callable[[CFGBranch], torch.Tensor | tuple[torch.Tensor, ...]],
|
|
bid: int,
|
|
branches,
|
|
) -> tuple[torch.Tensor, ...]:
|
|
branch = branches[bid]
|
|
device = get_local_torch_device()
|
|
local_branch = dataclasses.replace(
|
|
branch,
|
|
kwargs={
|
|
k: v.to(device) if isinstance(v, torch.Tensor) else v
|
|
for k, v in branch.kwargs.items()
|
|
},
|
|
)
|
|
raw = predict_fn(local_branch)
|
|
return _wrap(raw)
|
|
|
|
|
|
def run_cfg_parallel(
|
|
policy: CFGPolicy,
|
|
predict_fn: Callable[[CFGBranch], torch.Tensor | tuple[torch.Tensor, ...]],
|
|
) -> list[torch.Tensor | tuple[torch.Tensor, ...]]:
|
|
"""Dispatch CFG branches across ranks, all-gather results, return in branch order.
|
|
|
|
``predict_fn`` is a closure capturing all step-varying state
|
|
(latent_model_input, timestep, model, etc.). It is called with each
|
|
assigned ``CFGBranch`` and must return the raw ``_predict_noise`` output.
|
|
|
|
Idle ranks (cfg_world_size > n_branches) run branch 0 as a dummy forward
|
|
to obtain tensor shapes for the all-gather.
|
|
|
|
Returns a list indexed to match ``policy.branches``, identical on every rank.
|
|
"""
|
|
|
|
cfg_rank = get_classifier_free_guidance_rank()
|
|
cfg_world_size = get_classifier_free_guidance_world_size()
|
|
branches = policy.branches
|
|
n_branches = len(branches)
|
|
assignments = dispatch_branches(n_branches, cfg_world_size)
|
|
branches_assigned_to_local_rank = assignments[cfg_rank]
|
|
max_num_branches_per_rank = max(len(a) for a in assignments)
|
|
|
|
if cfg_world_size > n_branches:
|
|
logger.warning_once(
|
|
"cfg_parallel_size=%d > n_branches=%d; %d GPU(s) will be idle for CFG",
|
|
cfg_world_size,
|
|
n_branches,
|
|
cfg_world_size - n_branches,
|
|
)
|
|
|
|
dispatch_key = (n_branches, cfg_world_size, cfg_rank)
|
|
if dispatch_key not in _logged_dispatch_keys:
|
|
_logged_dispatch_keys.add(dispatch_key)
|
|
branch_names = (
|
|
[branches[i].name for i in branches_assigned_to_local_rank]
|
|
if branches_assigned_to_local_rank
|
|
else ["(idle)"]
|
|
)
|
|
logger.info(
|
|
"CFG parallel dispatch: rank %d/%d -> [%s]",
|
|
cfg_rank,
|
|
cfg_world_size,
|
|
", ".join(branch_names),
|
|
)
|
|
|
|
# perform the forward for local branches
|
|
predicts_from_local_branches: list[tuple[torch.Tensor, ...]] = [
|
|
_run(predict_fn, bid, branches) for bid in branches_assigned_to_local_rank
|
|
]
|
|
|
|
if not predicts_from_local_branches: # idle rank: run branch 0 for tensor shapes
|
|
predicts_from_local_branches.append(_run(predict_fn, 0, branches))
|
|
|
|
# pad the predicts to the length of max_num_branches_per_rank, to prepare for the all-gather later
|
|
ref = predicts_from_local_branches[0]
|
|
while len(predicts_from_local_branches) < max_num_branches_per_rank:
|
|
# TODO: cache this zero
|
|
predicts_from_local_branches.append(tuple(torch.zeros_like(t) for t in ref))
|
|
|
|
# All-gather each slot and output element with separate_tensors=True.
|
|
# all_slots[slot][elem] = list[Tensor] indexed by CFG rank; no reshape.
|
|
all_slots: list[list[list[torch.Tensor]]] = [
|
|
[
|
|
cfg_model_parallel_all_gather(p, dim=0, separate_tensors=True)
|
|
for p in slot_pred
|
|
]
|
|
for slot_pred in predicts_from_local_branches
|
|
]
|
|
|
|
# reorder the results in branch order: branch bid -> owner rank, slot.
|
|
n_elems = len(ref)
|
|
final: list[torch.Tensor | tuple[torch.Tensor, ...]] = []
|
|
for bid in range(n_branches):
|
|
owner = bid % cfg_world_size
|
|
slot = bid // cfg_world_size
|
|
elems = tuple(all_slots[slot][ei][owner] for ei in range(n_elems))
|
|
final.append(_unwrap(elems))
|
|
return final
|
|
|
|
|
|
def run_two_branch_cfg_parallel(
|
|
policy: CFGPolicy,
|
|
predict_fn: Callable[[CFGBranch], torch.Tensor | tuple[torch.Tensor, ...]],
|
|
cfg_scale: float,
|
|
batch,
|
|
pipeline_config,
|
|
) -> torch.Tensor | tuple[torch.Tensor, ...]:
|
|
"""Run standard two-pass CFG with the old all-reduce combine.
|
|
|
|
This keeps the existing WAN baselines: it avoids gathering both branch
|
|
predictions, and it preserves the bf16 arithmetic order used before the
|
|
multi-branch CFG dispatcher was added.
|
|
"""
|
|
|
|
cfg_rank = get_classifier_free_guidance_rank()
|
|
pred_t = _run(predict_fn, cfg_rank, policy.branches)
|
|
|
|
if cfg_rank == 0:
|
|
partial = tuple(cfg_scale * p for p in pred_t)
|
|
cond_t = pred_t
|
|
else:
|
|
partial = tuple((1 - cfg_scale) * p for p in pred_t)
|
|
cond_t = tuple(torch.empty_like(p) for p in pred_t)
|
|
|
|
results = [cfg_model_parallel_all_reduce(p) for p in partial]
|
|
cond_t = tuple(get_cfg_group().broadcast(p, src=0) for p in cond_t)
|
|
results[0] = _apply_cfg_postprocess(results[0], cond_t[0], batch, pipeline_config)
|
|
return _unwrap(tuple(results))
|
|
|
|
|
|
def dispatch_branches(n_branches: int, n_ranks: int) -> list[list[int]]:
|
|
"""Assign branches to ranks in Round-robin fashion
|
|
|
|
Returns a list of length ``n_ranks`` where element ``r`` contains the
|
|
branch indices assigned to rank ``r``. Branch ``i`` goes to rank
|
|
``i % n_ranks``.
|
|
|
|
Example: 4 passes, 2 GPUs:
|
|
rank 0 -> [0, 2], rank 1 -> [1, 3]
|
|
"""
|
|
assignments: list[list[int]] = [[] for _ in range(n_ranks)]
|
|
for i in range(n_branches):
|
|
assignments[i % n_ranks].append(i)
|
|
return assignments
|