Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2e6b4b5c7 |
No files matched your search
@@ -1,35 +1,46 @@
|
|||||||
|
# Focused weekly comparison against unchanged Omni main and official vLLM 0.30.0.
|
||||||
steps:
|
steps:
|
||||||
- label: ":docker: Build image"
|
- label: ':docker: Build image'
|
||||||
key: image-build
|
key: image-build
|
||||||
commands:
|
commands:
|
||||||
- "bash .buildkite/cuda/scripts/build-ci-image.sh"
|
- bash .buildkite/cuda/scripts/build-ci-image.sh
|
||||||
agents:
|
agents:
|
||||||
queue: "cpu_queue_premerge"
|
queue: cpu_queue_premerge
|
||||||
|
- label: Upload selected weekly baseline
|
||||||
# L2 Test
|
depends_on: image-build
|
||||||
- label: "Upload Ready Pipeline"
|
key: upload-weekly-pipeline
|
||||||
depends_on: image-build
|
commands:
|
||||||
key: upload-ready-pipeline
|
- |
|
||||||
commands:
|
python3 - <<'PYBASELINE'
|
||||||
- python3 .buildkite/common/scripts/upload_pipeline.py --upload --all .buildkite/cuda/test-ready.yml
|
import tempfile
|
||||||
agents:
|
from pathlib import Path
|
||||||
queue: "cpu_queue_premerge"
|
import yaml
|
||||||
|
labels = set(['TTS · Audex · CosyVoice · Qwen3-TTS · L4', 'TTS · H100', 'Diffusion · Bagel · H100 · Single-GPU', 'Diffusion · SenseNova-U1 · H100 · Single-GPU', 'Diffusion · DreamZero · H100 · 2-GPU', 'Diffusion · H100 · 4-GPU', 'Diffusion · MAGI-2 Preview Serving Smoke · H100 · 4-GPU'])
|
||||||
# L3 Test
|
source = yaml.safe_load(Path('.buildkite/cuda/test-weekly.yml').read_text())
|
||||||
- label: "Upload Merge Pipeline"
|
selected = set()
|
||||||
depends_on: image-build
|
guard = 'python3 -c \'import vllm, torch, flashinfer, vllm._C_stable_libtorch; assert vllm.__version__ == \'"\'"\'0.30.0\'"\'"\'; assert torch.cuda.is_available(); print(\'"\'"\'Verified baseline runtime:\'"\'"\', vllm.__version__, torch.__version__)\''
|
||||||
key: upload-merge-pipeline
|
def select(steps):
|
||||||
commands:
|
kept = []
|
||||||
- python3 .buildkite/common/scripts/upload_pipeline.py --upload --all .buildkite/cuda/test-merge.yml
|
for step in steps:
|
||||||
agents:
|
if not isinstance(step, dict):
|
||||||
queue: "cpu_queue_premerge"
|
continue
|
||||||
|
if 'steps' in step:
|
||||||
# L4 Test
|
children = select(step['steps'])
|
||||||
- label: "Upload Nightly Pipeline"
|
if children:
|
||||||
depends_on: image-build
|
kept.append(dict(step, steps=children))
|
||||||
key: upload-nightly-pipeline
|
elif step.get('label') in labels:
|
||||||
if: build.env("NIGHTLY") == "1"
|
item = dict(step)
|
||||||
commands:
|
commands = item['commands']
|
||||||
- python3 .buildkite/common/scripts/upload_pipeline.py --upload --all .buildkite/cuda/test-nightly.yml
|
item['commands'] = [guard] + ([commands] if isinstance(commands, str) else commands)
|
||||||
agents:
|
kept.append(item)
|
||||||
queue: "cpu_queue_premerge"
|
selected.add(item['label'])
|
||||||
|
return kept
|
||||||
|
source['steps'] = select(source['steps'])
|
||||||
|
assert selected == labels, (selected, labels)
|
||||||
|
path = Path(tempfile.gettempdir()) / 'vllm-omni-selected-weekly-baseline.yml'
|
||||||
|
path.write_text(yaml.safe_dump(source, sort_keys=False, allow_unicode=True))
|
||||||
|
print('Selected baseline suites:', sorted(selected), flush=True)
|
||||||
|
PYBASELINE
|
||||||
|
python3 .buildkite/common/scripts/upload_pipeline.py --upload --all /tmp/vllm-omni-selected-weekly-baseline.yml
|
||||||
|
agents:
|
||||||
|
queue: cpu_queue_premerge
|
||||||
@@ -36,7 +36,8 @@ RUN apt-get update && \
|
|||||||
# for CI
|
# for CI
|
||||||
COPY pyproject.toml setup.py ./
|
COPY pyproject.toml setup.py ./
|
||||||
COPY requirements/ requirements/
|
COPY requirements/ requirements/
|
||||||
ENV SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0
|
# Keep source-built dependency versions independent of the Omni CI version.
|
||||||
|
ENV VLLM_OMNI_VERSION_OVERRIDE=0.0.0
|
||||||
# Editable install: deps + project metadata are cached in this layer, while
|
# Editable install: deps + project metadata are cached in this layer, while
|
||||||
# the package itself is linked to APP_DIR (populated later by COPY --link).
|
# the package itself is linked to APP_DIR (populated later by COPY --link).
|
||||||
# Do NOT use a non-editable install here — that copies an empty stub into
|
# Do NOT use a non-editable install here — that copies an empty stub into
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ from typing import Literal
|
|||||||
import pytest
|
import pytest
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from tests.helpers.distributed import configure_cpu_collective_worker, start_collective_workers
|
|
||||||
from tests.helpers.mark import hardware_marks
|
from tests.helpers.mark import hardware_marks
|
||||||
from vllm_omni.diffusion.distributed.comm import RingComm, SeqAllToAll4D, SeqAllToAll5D
|
from vllm_omni.diffusion.distributed.comm import RingComm, SeqAllToAll4D, SeqAllToAll5D
|
||||||
from vllm_omni.diffusion.distributed.parallel_state import (
|
from vllm_omni.diffusion.distributed.parallel_state import (
|
||||||
@@ -57,8 +56,6 @@ def _init_worker(
|
|||||||
"MASTER_PORT": str(master_port),
|
"MASTER_PORT": str(master_port),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if device_kind == "cpu":
|
|
||||||
configure_cpu_collective_worker()
|
|
||||||
backend = "gloo" if device_kind == "cpu" else None
|
backend = "gloo" if device_kind == "cpu" else None
|
||||||
init_distributed_environment(backend=backend)
|
init_distributed_environment(backend=backend)
|
||||||
|
|
||||||
@@ -230,10 +227,6 @@ def _run_ring_p2p(
|
|||||||
atol=atol,
|
atol=atol,
|
||||||
msg=f"[Rank {local_rank}] Ring P2P data mismatch",
|
msg=f"[Rank {local_rank}] Ring P2P data mismatch",
|
||||||
)
|
)
|
||||||
if device_kind == "cpu":
|
|
||||||
# P2P completion only synchronizes neighbors. Keep fast CPU ranks
|
|
||||||
# alive until every rank has finished constructing and using groups.
|
|
||||||
torch.distributed.barrier()
|
|
||||||
finally:
|
finally:
|
||||||
destroy_distributed_env()
|
destroy_distributed_env()
|
||||||
|
|
||||||
@@ -250,7 +243,7 @@ def _spawn_4d_identity(
|
|||||||
device_kind: DeviceKind,
|
device_kind: DeviceKind,
|
||||||
master_port: int,
|
master_port: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
_run_4d_identity,
|
_run_4d_identity,
|
||||||
args=(
|
args=(
|
||||||
world_size,
|
world_size,
|
||||||
@@ -264,7 +257,6 @@ def _spawn_4d_identity(
|
|||||||
master_port,
|
master_port,
|
||||||
),
|
),
|
||||||
nprocs=world_size,
|
nprocs=world_size,
|
||||||
device_kind=device_kind,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -280,7 +272,7 @@ def _spawn_5d_identity(
|
|||||||
device_kind: DeviceKind,
|
device_kind: DeviceKind,
|
||||||
master_port: int,
|
master_port: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
_run_5d_identity,
|
_run_5d_identity,
|
||||||
args=(
|
args=(
|
||||||
world_size,
|
world_size,
|
||||||
@@ -294,7 +286,6 @@ def _spawn_5d_identity(
|
|||||||
master_port,
|
master_port,
|
||||||
),
|
),
|
||||||
nprocs=world_size,
|
nprocs=world_size,
|
||||||
device_kind=device_kind,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -308,11 +299,10 @@ def _spawn_ring_p2p(
|
|||||||
device_kind: DeviceKind,
|
device_kind: DeviceKind,
|
||||||
master_port: int,
|
master_port: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
_run_ring_p2p,
|
_run_ring_p2p,
|
||||||
args=(world_size, dtype, batch_size, num_heads, head_size, device_kind, master_port),
|
args=(world_size, dtype, batch_size, num_heads, head_size, device_kind, master_port),
|
||||||
nprocs=world_size,
|
nprocs=world_size,
|
||||||
device_kind=device_kind,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -509,9 +499,8 @@ def _run_fused_qkv_matches_three_4d(
|
|||||||
@pytest.mark.cpu
|
@pytest.mark.cpu
|
||||||
@pytest.mark.parametrize("world_size", [2, 4])
|
@pytest.mark.parametrize("world_size", [2, 4])
|
||||||
def test_fused_qkv_all_to_all_matches_three_4d_exchanges_cpu(world_size: int) -> None:
|
def test_fused_qkv_all_to_all_matches_three_4d_exchanges_cpu(world_size: int) -> None:
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
_run_fused_qkv_matches_three_4d,
|
_run_fused_qkv_matches_three_4d,
|
||||||
args=(world_size, "cpu", 29613),
|
args=(world_size, "cpu", 29613),
|
||||||
nprocs=world_size,
|
nprocs=world_size,
|
||||||
device_kind="cpu",
|
|
||||||
)
|
)
|
||||||
@@ -19,7 +19,6 @@ from vllm.utils.network_utils import get_file_store_init_method
|
|||||||
from vllm.v1.worker.gpu_worker import AsyncIntermediateTensors
|
from vllm.v1.worker.gpu_worker import AsyncIntermediateTensors
|
||||||
|
|
||||||
import vllm_omni.diffusion.distributed.pipeline_parallel as pp_module
|
import vllm_omni.diffusion.distributed.pipeline_parallel as pp_module
|
||||||
from tests.helpers.distributed import collective_context, start_collective_workers
|
|
||||||
from tests.helpers.mark import hardware_marks
|
from tests.helpers.mark import hardware_marks
|
||||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||||
from vllm_omni.diffusion.distributed.parallel_state import (
|
from vllm_omni.diffusion.distributed.parallel_state import (
|
||||||
@@ -40,25 +39,6 @@ DeviceKind = Literal["cpu", "cuda"]
|
|||||||
_UNIT_MARKS = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu]
|
_UNIT_MARKS = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
|
||||||
def _restore_collective_platforms():
|
|
||||||
"""CPU baselines run in the parent process; retain its original platforms."""
|
|
||||||
import vllm.platforms
|
|
||||||
|
|
||||||
from vllm_omni.diffusion.distributed import comm, group_coordinator, parallel_state
|
|
||||||
|
|
||||||
original_platform = vllm.platforms.current_platform
|
|
||||||
original_omni_platforms = {
|
|
||||||
module: module.current_omni_platform for module in (comm, group_coordinator, parallel_state)
|
|
||||||
}
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
finally:
|
|
||||||
vllm.platforms.current_platform = original_platform
|
|
||||||
for module, platform in original_omni_platforms.items():
|
|
||||||
module.current_omni_platform = platform
|
|
||||||
|
|
||||||
|
|
||||||
def _cleanup_distributed() -> None:
|
def _cleanup_distributed() -> None:
|
||||||
"""Destroy omni distributed state left dangling after a test.
|
"""Destroy omni distributed state left dangling after a test.
|
||||||
|
|
||||||
@@ -429,10 +409,6 @@ def init_dist(
|
|||||||
device = _worker_device(local_rank, device_kind)
|
device = _worker_device(local_rank, device_kind)
|
||||||
if device_kind == "cuda":
|
if device_kind == "cuda":
|
||||||
current_omni_platform.set_device(device)
|
current_omni_platform.set_device(device)
|
||||||
else:
|
|
||||||
from tests.helpers.distributed import configure_cpu_collective_worker
|
|
||||||
|
|
||||||
configure_cpu_collective_worker()
|
|
||||||
backend = "gloo" if device_kind == "cpu" else None
|
backend = "gloo" if device_kind == "cpu" else None
|
||||||
init_distributed_environment(
|
init_distributed_environment(
|
||||||
world_size=world_size,
|
world_size=world_size,
|
||||||
@@ -524,14 +500,13 @@ def isend_irecv_worker(
|
|||||||
|
|
||||||
|
|
||||||
def _run_isend_irecv(pp_size: int, device_kind: DeviceKind, init_method: str) -> None:
|
def _run_isend_irecv(pp_size: int, device_kind: DeviceKind, init_method: str) -> None:
|
||||||
mp_context = collective_context(device_kind)
|
mp_context = torch.multiprocessing.get_context("spawn")
|
||||||
manager = mp_context.Manager()
|
manager = mp_context.Manager()
|
||||||
q = manager.Queue()
|
q = manager.Queue()
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
isend_irecv_worker,
|
isend_irecv_worker,
|
||||||
args=(pp_size, init_method, device_kind, q),
|
args=(pp_size, init_method, device_kind, q),
|
||||||
nprocs=pp_size,
|
nprocs=pp_size,
|
||||||
device_kind=device_kind,
|
|
||||||
)
|
)
|
||||||
results = {label: tensor for label, tensor in [q.get(), q.get()]}
|
results = {label: tensor for label, tensor in [q.get(), q.get()]}
|
||||||
torch.testing.assert_close(
|
torch.testing.assert_close(
|
||||||
@@ -681,16 +656,15 @@ def _run_predict_noise(
|
|||||||
|
|
||||||
baseline_out = compute_single_gpu_baseline(test_config, dtype, do_true_cfg, device_kind)
|
baseline_out = compute_single_gpu_baseline(test_config, dtype, do_true_cfg, device_kind)
|
||||||
|
|
||||||
mp_context = collective_context(device_kind)
|
mp_context = torch.multiprocessing.get_context("spawn")
|
||||||
manager = mp_context.Manager()
|
manager = mp_context.Manager()
|
||||||
pp_q = manager.Queue()
|
pp_q = manager.Queue()
|
||||||
|
|
||||||
world_size = pp_size * cfg_size
|
world_size = pp_size * cfg_size
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
predict_noise_worker,
|
predict_noise_worker,
|
||||||
args=(world_size, init_method, pp_size, cfg_size, do_true_cfg, dtype, test_config, device_kind, pp_q),
|
args=(world_size, init_method, pp_size, cfg_size, do_true_cfg, dtype, test_config, device_kind, pp_q),
|
||||||
nprocs=world_size,
|
nprocs=world_size,
|
||||||
device_kind=device_kind,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pp_out = pp_q.get()
|
pp_out = pp_q.get()
|
||||||
@@ -926,16 +900,15 @@ def _run_scheduler_step(
|
|||||||
|
|
||||||
baseline = compute_scheduler_step_baseline(test_config, do_true_cfg, device_kind)
|
baseline = compute_scheduler_step_baseline(test_config, do_true_cfg, device_kind)
|
||||||
|
|
||||||
mp_context = collective_context(device_kind)
|
mp_context = torch.multiprocessing.get_context("spawn")
|
||||||
manager = mp_context.Manager()
|
manager = mp_context.Manager()
|
||||||
q = manager.Queue()
|
q = manager.Queue()
|
||||||
|
|
||||||
world_size = pp_size * cfg_size
|
world_size = pp_size * cfg_size
|
||||||
start_collective_workers(
|
torch.multiprocessing.spawn(
|
||||||
scheduler_step_worker,
|
scheduler_step_worker,
|
||||||
args=(world_size, init_method, pp_size, cfg_size, do_true_cfg, test_config, device_kind, q),
|
args=(world_size, init_method, pp_size, cfg_size, do_true_cfg, test_config, device_kind, q),
|
||||||
nprocs=world_size,
|
nprocs=world_size,
|
||||||
device_kind=device_kind,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
result = q.get()
|
result = q.get()
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
|
||||||
"""Import preload for the CPU-only collective forkserver.
|
|
||||||
|
|
||||||
This module is imported in the forkserver process, before it starts workers.
|
|
||||||
Its CUDA visibility does not alter the pytest process or CUDA parity workers.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
os.environ["CUDA_VISIBLE_DEVICES"] = ""
|
|
||||||
|
|
||||||
import torch # noqa: E402
|
|
||||||
|
|
||||||
# Retain the expensive worker-module imports across CPU process groups.
|
|
||||||
from tests.diffusion.distributed import test_comm, test_pipeline_parallel # noqa: E402, F401
|
|
||||||
|
|
||||||
if torch.cuda.is_initialized():
|
|
||||||
raise RuntimeError("CPU collective forkserver must not initialize CUDA")
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
|
||||||
"""Process and platform setup for isolated collective test workers."""
|
|
||||||
|
|
||||||
from collections.abc import Callable
|
|
||||||
from multiprocessing.context import BaseContext
|
|
||||||
|
|
||||||
import torch
|
|
||||||
|
|
||||||
|
|
||||||
def collective_context(device_kind: str) -> BaseContext:
|
|
||||||
"""Reuse imports in a clean CPU forkserver; CUDA workers use spawn."""
|
|
||||||
if device_kind == "cpu" and "forkserver" in torch.multiprocessing.get_all_start_methods():
|
|
||||||
torch.multiprocessing.set_forkserver_preload(["tests.helpers.cpu_collective_server"])
|
|
||||||
return torch.multiprocessing.get_context("forkserver")
|
|
||||||
return torch.multiprocessing.get_context("spawn")
|
|
||||||
|
|
||||||
|
|
||||||
def start_collective_workers(
|
|
||||||
worker: Callable[..., None], *, args: tuple[object, ...], nprocs: int, device_kind: str
|
|
||||||
) -> None:
|
|
||||||
context = collective_context(device_kind)
|
|
||||||
if context.get_start_method() == "spawn":
|
|
||||||
torch.multiprocessing.spawn(worker, args=args, nprocs=nprocs)
|
|
||||||
else:
|
|
||||||
torch.multiprocessing.start_processes(worker, args=args, nprocs=nprocs, start_method=context.get_start_method())
|
|
||||||
|
|
||||||
|
|
||||||
def configure_cpu_collective_worker() -> None:
|
|
||||||
"""Select CPU platforms inside a spawned worker that only uses Gloo.
|
|
||||||
|
|
||||||
Upstream coordinators resolve local ranks through the selected
|
|
||||||
platform's visible devices. CPU ranks can outnumber visible GPUs, so they
|
|
||||||
must use the CPU platform even when the test host has CUDA installed.
|
|
||||||
The worker still creates real process groups and runs real collectives.
|
|
||||||
"""
|
|
||||||
import vllm.platforms
|
|
||||||
from vllm.platforms.cpu import CpuPlatform
|
|
||||||
|
|
||||||
from vllm_omni.diffusion.distributed import comm, group_coordinator, parallel_state
|
|
||||||
from vllm_omni.platforms.interface import UnspecifiedOmniPlatform
|
|
||||||
|
|
||||||
class CpuCollectivePlatform(UnspecifiedOmniPlatform):
|
|
||||||
dist_backend = "gloo"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_device_count(cls) -> int:
|
|
||||||
# CPU tensors share one logical device regardless of process rank.
|
|
||||||
return 1
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_device(cls, device: torch.device) -> None:
|
|
||||||
assert device.type == "cpu"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def synchronize(cls) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
vllm.platforms.current_platform = CpuPlatform()
|
|
||||||
platform = CpuCollectivePlatform()
|
|
||||||
for module in (comm, group_coordinator, parallel_state):
|
|
||||||
module.current_omni_platform = platform
|
|
||||||
Reference in new issue
Block a user