chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
"""
|
||||
Mixin class providing multiplexing scheduling logic
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
import torch
|
||||
import torch.distributed as dist
|
||||
from torch.cuda.streams import ExternalStream
|
||||
|
||||
from sglang.srt.distributed.parallel_state import set_pdmux_status
|
||||
from sglang.srt.model_executor.forward_batch_info import ForwardMode
|
||||
from sglang.srt.multiplex.pdmux_context import (
|
||||
get_current_stream_idx,
|
||||
get_sm_counts,
|
||||
get_stream_groups,
|
||||
initialize_stream_groups,
|
||||
load_pdmux_config,
|
||||
set_current_stream_idx,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sglang.srt.managers.schedule_batch import ScheduleBatch
|
||||
from sglang.srt.managers.scheduler import Scheduler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SchedulerMultiplexMixin:
|
||||
|
||||
def init_pdmux(self: Scheduler):
|
||||
# The current split prefill batch
|
||||
self.split_prefill_batch: Optional[ScheduleBatch] = None
|
||||
|
||||
# for pd_multiplexing, Init stream_groups, exclude normal stream for prefill only and decode only
|
||||
self.pdmux_config = load_pdmux_config(self.server_args.pdmux_config_path)
|
||||
initialize_stream_groups(self.gpu_id, self.pdmux_config)
|
||||
self.stream_groups = get_stream_groups()
|
||||
self.sm_counts = get_sm_counts()
|
||||
self.real_sm_group_num = len(self.stream_groups)
|
||||
logger.info(
|
||||
f"PD-Multiplexing enabled with {self.real_sm_group_num} stream groups, sm_counts (prefill_sm, decode_sm): {self.sm_counts}"
|
||||
)
|
||||
|
||||
# TODO(jason-fxz): This is a temporary demo
|
||||
def adjust_stream_groups(
|
||||
self: Scheduler,
|
||||
) -> tuple[int, tuple[ExternalStream, ExternalStream]]:
|
||||
if not self.running_batch.is_empty() and self.split_prefill_batch:
|
||||
decode_bs = self.running_batch.batch_size()
|
||||
manual_divisions = self.pdmux_config.manual_divisions
|
||||
if manual_divisions:
|
||||
for i in range(len(manual_divisions)):
|
||||
_, _, threshold = manual_divisions[i]
|
||||
if decode_bs >= threshold:
|
||||
stream_idx = i + 1
|
||||
else:
|
||||
stream_idx = max(
|
||||
1,
|
||||
min(
|
||||
self.real_sm_group_num - 2,
|
||||
decode_bs
|
||||
* (self.real_sm_group_num - 2)
|
||||
// self.pdmux_config.decode_bs_divisor,
|
||||
),
|
||||
)
|
||||
set_current_stream_idx(stream_idx)
|
||||
elif not self.running_batch.is_empty():
|
||||
set_current_stream_idx(self.real_sm_group_num - 1)
|
||||
else:
|
||||
set_current_stream_idx(0)
|
||||
|
||||
stream_idx = get_current_stream_idx()
|
||||
|
||||
self.tp_worker.model_runner.update_decode_attn_backend(stream_idx)
|
||||
return stream_idx, self.stream_groups[stream_idx]
|
||||
|
||||
def update_split_prefill_batch(self: Scheduler, sm_count: int) -> bool:
|
||||
if self.split_prefill_batch:
|
||||
return False
|
||||
|
||||
# add new request
|
||||
prefill_plan = self.get_new_batch_prefill(self.running_batch)
|
||||
batch = prefill_plan.batch_to_run
|
||||
self.running_batch = prefill_plan.running_batch
|
||||
if batch and not batch.is_empty():
|
||||
batch.forward_mode = (
|
||||
ForwardMode.SPLIT_PREFILL
|
||||
) # Set forward mode for split prefill
|
||||
self.split_prefill_batch = batch
|
||||
return True
|
||||
return False
|
||||
|
||||
@torch.inference_mode()
|
||||
def event_loop_pdmux(self: Scheduler):
|
||||
"""A scheduler loop for pd multiplexing."""
|
||||
decode_done = False
|
||||
prefill_done = False
|
||||
wait_prefill_kernel_done = False
|
||||
adjust_stream_group = False
|
||||
stream_idx = get_current_stream_idx()
|
||||
stream_group = self.stream_groups[stream_idx]
|
||||
prefill_stream = stream_group[0]
|
||||
decode_stream = stream_group[1]
|
||||
torch.cuda.empty_cache()
|
||||
|
||||
logger.debug("Starting event loop for pd multiplexing...")
|
||||
|
||||
while True:
|
||||
with torch.cuda.stream(decode_stream):
|
||||
set_pdmux_status(False)
|
||||
recv_reqs = self.request_receiver.recv_requests()
|
||||
self.process_input_requests(recv_reqs)
|
||||
|
||||
with torch.cuda.stream(prefill_stream):
|
||||
set_pdmux_status(True)
|
||||
sm_count = self.sm_counts[stream_idx][0]
|
||||
if not wait_prefill_kernel_done:
|
||||
adjust_stream_group = (
|
||||
self.update_split_prefill_batch(sm_count) or adjust_stream_group
|
||||
)
|
||||
|
||||
with torch.cuda.stream(decode_stream):
|
||||
set_pdmux_status(False)
|
||||
self.running_batch = self.update_running_batch(self.running_batch)
|
||||
adjust_stream_group = adjust_stream_group or (
|
||||
stream_idx > 0 and self.running_batch.is_empty()
|
||||
)
|
||||
if self.running_batch.is_empty() and self.split_prefill_batch is None:
|
||||
self.on_idle()
|
||||
|
||||
if adjust_stream_group:
|
||||
prefill_stream.synchronize()
|
||||
decode_stream.synchronize()
|
||||
stream_idx, stream_group = self.adjust_stream_groups()
|
||||
prefill_stream = stream_group[0]
|
||||
decode_stream = stream_group[1]
|
||||
adjust_stream_group = False
|
||||
logger.debug(
|
||||
f"Adjusting stream groups: {stream_idx}, prefill sm: {self.sm_counts[stream_idx][0]}, decode sm: {self.sm_counts[stream_idx][1]}"
|
||||
)
|
||||
|
||||
with torch.cuda.stream(decode_stream):
|
||||
set_pdmux_status(False)
|
||||
# process decode batch
|
||||
if self.running_batch and not self.running_batch.is_empty():
|
||||
decode_result = self.run_batch(self.running_batch)
|
||||
decode_done = True
|
||||
else:
|
||||
decode_done = False
|
||||
with torch.cuda.stream(prefill_stream):
|
||||
set_pdmux_status(True)
|
||||
if (
|
||||
self.split_prefill_batch
|
||||
and not self.split_prefill_batch.is_empty()
|
||||
and not wait_prefill_kernel_done
|
||||
):
|
||||
prefill_done = True
|
||||
forward_count = (
|
||||
max(
|
||||
1,
|
||||
self.pdmux_config.split_forward_token_budget
|
||||
// self.split_prefill_batch.extend_num_tokens,
|
||||
)
|
||||
if self.split_prefill_batch.extend_num_tokens > 0
|
||||
else self.model_config.num_hidden_layers
|
||||
)
|
||||
next_split_index = min(
|
||||
self.split_prefill_batch.split_index + forward_count,
|
||||
self.model_config.num_hidden_layers,
|
||||
)
|
||||
forward_count = (
|
||||
next_split_index - self.split_prefill_batch.split_index
|
||||
)
|
||||
|
||||
self.split_prefill_batch.split_forward_count = forward_count
|
||||
prefill_result = self.run_batch(self.split_prefill_batch)
|
||||
if next_split_index == self.model_config.num_hidden_layers:
|
||||
self.split_prefill_batch.split_prefill_finished = True
|
||||
prefill_exe_done = prefill_stream.record_event()
|
||||
self.split_prefill_batch.split_index = next_split_index
|
||||
|
||||
elif wait_prefill_kernel_done:
|
||||
prefill_done = True
|
||||
else:
|
||||
prefill_done = False
|
||||
|
||||
with torch.cuda.stream(decode_stream):
|
||||
set_pdmux_status(False)
|
||||
decode_stream.synchronize()
|
||||
if decode_done:
|
||||
self.process_batch_result(self.running_batch, decode_result)
|
||||
|
||||
with torch.cuda.stream(prefill_stream):
|
||||
set_pdmux_status(True)
|
||||
if prefill_done and self.split_prefill_batch.split_prefill_finished:
|
||||
wait_prefill_kernel_done = True
|
||||
prefill_exe_done_flag = prefill_exe_done.query()
|
||||
flags = (
|
||||
torch.ones(1, device="cpu", dtype=torch.int32)
|
||||
if prefill_exe_done_flag
|
||||
else torch.zeros(1, device="cpu", dtype=torch.int32)
|
||||
)
|
||||
|
||||
self.tp_cpu_group.allreduce(flags, dist.ReduceOp.SUM).wait()
|
||||
if flags.item() == self.tp_size:
|
||||
self.process_batch_result(
|
||||
self.split_prefill_batch, prefill_result
|
||||
)
|
||||
if self.running_batch and not self.running_batch.is_empty():
|
||||
self.running_batch.merge_batch(self.split_prefill_batch)
|
||||
else:
|
||||
self.running_batch = self.split_prefill_batch
|
||||
|
||||
self.split_prefill_batch = None
|
||||
wait_prefill_kernel_done = False
|
||||
adjust_stream_group = True
|
||||
@@ -0,0 +1,164 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
|
||||
import torch
|
||||
import yaml
|
||||
|
||||
STREAM_GROUPS = []
|
||||
SM_COUNTS = []
|
||||
SM_GROUP_NUM = 8 # Default number of SM groups
|
||||
CURRENT_STREAM_IDX = 0
|
||||
CURRENT_STREAM_GROUP = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class PDMuxConfig:
|
||||
sm_group_num: int = 8
|
||||
manual_divisions: List[List[int]] = field(
|
||||
default_factory=list
|
||||
) # [prefill_sm, decode_sm, decode_bs_threshold]
|
||||
split_forward_token_budget: int = 65536
|
||||
decode_bs_divisor: int = 36
|
||||
|
||||
|
||||
def load_pdmux_config(config_path: str) -> PDMuxConfig:
|
||||
"""Load pdmux configuration from YAML file into a dataclass."""
|
||||
if not config_path:
|
||||
return PDMuxConfig()
|
||||
|
||||
with open(config_path, "r") as f:
|
||||
raw = yaml.safe_load(f)
|
||||
|
||||
if "sm_group_num" not in raw:
|
||||
raise ValueError("Missing required field: sm_group_num")
|
||||
|
||||
if raw["sm_group_num"] < 3:
|
||||
raise ValueError("sm_group_num must be >= 3")
|
||||
|
||||
manual_divisions = raw.get("manual_divisions", [])
|
||||
|
||||
expected = raw["sm_group_num"] - 2
|
||||
if manual_divisions and len(manual_divisions) != expected:
|
||||
raise ValueError(
|
||||
f"manual_divisions must have {expected} entries, "
|
||||
f"but got {len(manual_divisions)}"
|
||||
)
|
||||
|
||||
return PDMuxConfig(
|
||||
sm_group_num=raw["sm_group_num"],
|
||||
manual_divisions=manual_divisions,
|
||||
split_forward_token_budget=raw.get("split_forward_token_budget", 65536),
|
||||
decode_bs_divisor=raw.get("decode_bs_divisor", 36),
|
||||
)
|
||||
|
||||
|
||||
def get_arch_constraints(compute_capability):
|
||||
major, minor = compute_capability
|
||||
# green context constraints for different architectures
|
||||
if major == 6:
|
||||
return 1, 1 # min_per_part, multiple
|
||||
elif major == 7:
|
||||
return 2, 2
|
||||
elif major == 8:
|
||||
return 4, 2
|
||||
elif major == 9 and minor >= 0:
|
||||
return 8, 8
|
||||
else:
|
||||
raise ValueError(f"Unsupported compute capability: {major}.{minor}")
|
||||
|
||||
|
||||
def divide_sm(total_sms, compute_capability, groups):
|
||||
"""
|
||||
:param total_sms: total sm count on a single GPU
|
||||
:param compute_capability: (major, minor)
|
||||
:return: SM partition group(prefill sm, decode sm)
|
||||
"""
|
||||
min_per_part, multiple = get_arch_constraints(compute_capability)
|
||||
possible_values = [
|
||||
x
|
||||
for x in range(min_per_part, total_sms - min_per_part + 1, multiple)
|
||||
if x >= total_sms - x and total_sms - x >= 16
|
||||
]
|
||||
if not possible_values:
|
||||
raise ValueError(
|
||||
f"No valid partitions found for total SMs {total_sms} "
|
||||
f"with constraints (min per part: {min_per_part}, multiple: {multiple})"
|
||||
)
|
||||
|
||||
if len(possible_values) >= groups:
|
||||
step = max(1, len(possible_values) // groups)
|
||||
selected_values = possible_values[::step][:groups]
|
||||
else:
|
||||
selected_values = possible_values
|
||||
|
||||
divisions = []
|
||||
for part1 in selected_values:
|
||||
part2 = total_sms - part1
|
||||
divisions.append((part1, part2))
|
||||
|
||||
divisions.reverse() # Reverse to have larger prefill SM first
|
||||
|
||||
return divisions
|
||||
|
||||
|
||||
def initialize_stream_groups(gpu_id: int, config: PDMuxConfig):
|
||||
from sgl_kernel import spatial
|
||||
|
||||
global STREAM_GROUPS, SM_COUNTS, SM_GROUP_NUM, CURRENT_STREAM_IDX, CURRENT_STREAM_GROUP
|
||||
# for pd_multiplexing, Init stream_groups
|
||||
device = torch.cuda.current_device()
|
||||
total_sm_count = spatial.get_sm_available(gpu_id)
|
||||
# (prefill_sm_count, decode_sm_count)
|
||||
if config.manual_divisions:
|
||||
divisions = [
|
||||
(prefill_sm, decode_sm)
|
||||
for prefill_sm, decode_sm, _ in config.manual_divisions
|
||||
]
|
||||
else:
|
||||
divisions = divide_sm(
|
||||
total_sm_count,
|
||||
torch.cuda.get_device_capability(device),
|
||||
config.sm_group_num - 2,
|
||||
)
|
||||
|
||||
SM_COUNTS = []
|
||||
SM_COUNTS.append((total_sm_count, 0)) # Normal stream for prefill
|
||||
SM_COUNTS.extend(divisions) # Add the divided SM counts
|
||||
SM_COUNTS.append((0, total_sm_count)) # Normal stream for decode
|
||||
STREAM_GROUPS = []
|
||||
STREAM_GROUPS.append(
|
||||
(torch.cuda.Stream(gpu_id), torch.cuda.Stream(gpu_id))
|
||||
) # Normal stream for prefill
|
||||
for prefill_sm, decode_sm in divisions:
|
||||
STREAM_GROUPS.append(
|
||||
(spatial.create_greenctx_stream_by_value(prefill_sm, decode_sm, gpu_id))
|
||||
)
|
||||
STREAM_GROUPS.append(
|
||||
(torch.cuda.Stream(gpu_id), torch.cuda.Stream(gpu_id))
|
||||
) # Normal stream for decode
|
||||
|
||||
CURRENT_STREAM_IDX = 0
|
||||
CURRENT_STREAM_GROUP = STREAM_GROUPS[CURRENT_STREAM_IDX]
|
||||
|
||||
|
||||
def set_current_stream_idx(idx: int):
|
||||
global CURRENT_STREAM_IDX, CURRENT_STREAM_GROUP
|
||||
if idx < 0 or idx >= len(STREAM_GROUPS):
|
||||
raise ValueError(f"Invalid stream index: {idx}")
|
||||
CURRENT_STREAM_IDX = idx
|
||||
CURRENT_STREAM_GROUP = STREAM_GROUPS[CURRENT_STREAM_IDX]
|
||||
|
||||
|
||||
def get_stream_groups() -> list[tuple[torch.cuda.Stream, torch.cuda.Stream]]:
|
||||
"""Get the stream groups."""
|
||||
return STREAM_GROUPS
|
||||
|
||||
|
||||
def get_sm_counts() -> list[tuple[int, int]]:
|
||||
"""Get the SM counts."""
|
||||
return SM_COUNTS
|
||||
|
||||
|
||||
def get_current_stream_idx() -> int:
|
||||
"""Get the current stream index."""
|
||||
return CURRENT_STREAM_IDX
|
||||
Reference in New Issue
Block a user