Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
b1623ca
feat: add unified LightSpec speculative decoding
flyinglandlord Aug 4, 2026
0b00906
add qwen3.5 dflash support
Owleye4 Aug 4, 2026
464bc48
remove dflash dynamic draft & add qwen35 dspark
shihaobai Aug 5, 2026
8a75a1f
WIP: simplify LightSpec implementation (not ready for review)
shihaobai Aug 10, 2026
6aea8ce
fix: read Qwen3.5 target layers from text config
shihaobai Aug 10, 2026
3f2ee16
refactor: simplify LightSpec draft integration
shihaobai Aug 11, 2026
9aa6dfc
refactor: simplify speculative decoding pipeline
shihaobai Aug 11, 2026
f5293ba
fix: align speculative draft inputs and DSpark RoPE
shihaobai Aug 11, 2026
f713b82
refactor: simplify dynamic speculative scheduling
shihaobai Aug 13, 2026
640036f
Merge remote-tracking branch 'origin/main' into lightspec
shihaobai Aug 13, 2026
2870d32
fix: stabilize dynamic speculative scheduling
shihaobai Aug 14, 2026
ee0ab34
refactor: centralize MTP decode batch layout
hiworldwzj Aug 14, 2026
c65ae9c
refactor: clarify MTP CUDA graph batch sizing
hiworldwzj Aug 14, 2026
dee4749
refactor: centralize MTP decode draft step
hiworldwzj Aug 14, 2026
fe70b2f
refactor: isolate hidden collector inference state
hiworldwzj Aug 17, 2026
249667f
refactor: reuse forward in autotune warmup
hiworldwzj Aug 17, 2026
55cf376
fix
hiworldwzj Aug 17, 2026
56421db
refactor: initialize decode group metadata on demand
hiworldwzj Aug 17, 2026
b25e38f
refactor: split FA3 decode state initialization
hiworldwzj Aug 17, 2026
8f32f61
refactor: move FA3 causality into attention state
hiworldwzj Aug 17, 2026
538189a
refactor: align linear attention MTP state naming
hiworldwzj Aug 17, 2026
552b02a
refactor: clarify MTP SSM buffer shape
hiworldwzj Aug 17, 2026
a423012
refactor: share GPU attention workspaces
hiworldwzj Aug 17, 2026
4e18cee
fix
hiworldwzj Aug 17, 2026
027ce10
refactor: move FA3 utility test to file end
hiworldwzj Aug 17, 2026
bf339c1
refactor: align MTP utility naming
hiworldwzj Aug 17, 2026
35cc0ff
fix: clarify MRoPE positions for draft cache extension
hiworldwzj Aug 18, 2026
7fa888f
refactor: split draft model registry
hiworldwzj Aug 18, 2026
9704c20
refactor: rename dynamic MTP flag
hiworldwzj Aug 18, 2026
7b708d5
refactor: remove unused MTP Gloo group
hiworldwzj Aug 18, 2026
d3e657f
refactor: build MTP group markers from request IDs
hiworldwzj Aug 18, 2026
dca9fea
refactor: simplify padded MTP group markers
hiworldwzj Aug 18, 2026
c82f283
refactor: rename speculative package
hiworldwzj Aug 18, 2026
ef43e58
refactor: align MTP metric method names
hiworldwzj Aug 18, 2026
e5f81a0
refactor: make MTP KV layer counts explicit
hiworldwzj Aug 18, 2026
637719e
refactor: unify MTP model outputs
hiworldwzj Aug 18, 2026
76faef9
refactor: clarify MTP output collector naming
hiworldwzj Aug 18, 2026
3dce9ac
refactor: clarify proposal coverage state
hiworldwzj Aug 18, 2026
ce15142
refactor: split speculative planners into package
hiworldwzj Aug 18, 2026
cec8624
refactor: pass decode requests to planners
hiworldwzj Aug 18, 2026
5963199
refactor: move draft step selection to planner
hiworldwzj Aug 18, 2026
6e25ddc
refactor: move MTP cost modeling to planners
hiworldwzj Aug 18, 2026
9a3cb61
refactor: require CUDA graphs for MTP planning
hiworldwzj Aug 19, 2026
4921565
refactor: add common MTP planner interface
hiworldwzj Aug 19, 2026
46b04e8
chore: add DP MTP extension packages
hiworldwzj Aug 19, 2026
45a21d4
refactor: separate DP MTP engines and proposers
hiworldwzj Aug 19, 2026
addeab4
refactor: unify fixed and dynamic MTP decode plans
hiworldwzj Aug 19, 2026
4113a46
refactor: extract shared MTP decode utilities
hiworldwzj Aug 19, 2026
f78238f
refactor: simplify MTP decode request handling
hiworldwzj Aug 19, 2026
29940cb
refactor: clarify MTP planner interfaces
hiworldwzj Aug 19, 2026
c5c941a
refactor: type MTP backend dependencies
hiworldwzj Aug 19, 2026
f3b0b44
refactor: centralize MTP memory allocation
hiworldwzj Aug 19, 2026
6455a15
refactor: specialize MTP proposal handling
hiworldwzj Aug 19, 2026
accdcdf
refactor: unify MTP proposal memory release
hiworldwzj Aug 19, 2026
9a00892
refactor: simplify dynamic MTP memory handling
hiworldwzj Aug 19, 2026
b135abe
refactor: separate dynamic MTP kernels
hiworldwzj Aug 19, 2026
36261cf
refactor: clarify MTP verify batch shape
hiworldwzj Aug 19, 2026
1dffe62
refactor: unify MTP proposal token layout
hiworldwzj Aug 19, 2026
14e7bba
refactor: clarify MTP metric and memory handling
hiworldwzj Aug 19, 2026
79e6196
refactor: rename draft KV state initialization
hiworldwzj Aug 19, 2026
b868bf7
refactor: clarify target token inputs for draft KV fill
hiworldwzj Aug 19, 2026
4696ba9
refactor: clarify target proposal inputs
hiworldwzj Aug 19, 2026
5743624
refactor: skip vanilla no-att draft state fill
hiworldwzj Aug 20, 2026
46c8bda
refactor: build MTP attention groups in backends
hiworldwzj Aug 20, 2026
ee69b52
refactor: rebuild diverse groups from radix metadata
hiworldwzj Aug 20, 2026
b3bf319
refactor: tighten model input phase contracts
hiworldwzj Aug 20, 2026
8aead20
perf: fuse vanilla MTP row selection
hiworldwzj Aug 20, 2026
69768e0
refactor: localize MTP prefill state preparation
hiworldwzj Aug 20, 2026
2ed5212
fix: keep vanilla attention draft depth fixed
hiworldwzj Aug 20, 2026
515d71d
fix: cascade vanilla attention decode inputs
hiworldwzj Aug 20, 2026
6fde882
refactor: isolate vanilla proposer implementations
hiworldwzj Aug 20, 2026
d0def76
refactor: specialize eagle no-att proposal flow
hiworldwzj Aug 20, 2026
5059c4d
refactor: specialize eagle attention proposal flow
hiworldwzj Aug 20, 2026
8442a18
refactor: centralize MTP proposal types
hiworldwzj Aug 20, 2026
320d7f9
refactor: relocate DP EAGLE helpers
hiworldwzj Aug 20, 2026
6cd7d8a
refactor: specialize parallel MTP proposers
hiworldwzj Aug 20, 2026
487f448
refactor: derive prefill token count from input ids
hiworldwzj Aug 20, 2026
144cd30
refactor dp padding into base model
hiworldwzj Aug 21, 2026
a073518
remove redundant prefix token count
hiworldwzj Aug 21, 2026
4932e33
refactor: simplify overlap input preparation
hiworldwzj Aug 21, 2026
a8659f1
fix: account for MTP weights in KV cache profiling (#1478)
shihaobai Aug 21, 2026
d09c5c9
fix(dspark): support partial rotary checkpoints
sufubao Aug 21, 2026
29ec9f2
dspark infer fix
Aug 21, 2026
481b344
feat: add qwen3.5 1p1d dspark launch script
shihaobai Aug 21, 2026
9f2fe17
refactor: reuse common speculative engine for dp
hiworldwzj Aug 21, 2026
4398e9a
fix: synchronize dynamic LightSpec draft steps across dp
hiworldwzj Aug 21, 2026
b9957ab
chore: add DSpark 1P1D deployment script
sufubao Aug 21, 2026
15641f3
fix: pad empty speculative hidden states
hiworldwzj Aug 21, 2026
8f92128
refactor: encapsulate dp overlap proposal inputs
hiworldwzj Aug 21, 2026
acb6532
refactor dp overlap speculative scheduling
hiworldwzj Aug 22, 2026
f0f38e6
refactor dp overlap eagle proposers
hiworldwzj Aug 22, 2026
414c39b
fix: honor qwen3 eagle attention head dim
hiworldwzj Aug 22, 2026
e56d533
Use workspace buffers for FA3 page tables
hiworldwzj Aug 23, 2026
e745657
Rename chained MTP decode input builder
hiworldwzj Aug 23, 2026
6451589
Fix MTP sampling buffer width
hiworldwzj Aug 23, 2026
e7c80c8
Restrict diverse MTP modes to no-attention
hiworldwzj Aug 23, 2026
9bb1a27
Simplify DP overlap prefill token slicing
hiworldwzj Aug 23, 2026
969ba1a
Simplify DP prefill real-shape handling
hiworldwzj Aug 23, 2026
b3eb120
Require MTP row indexes during verification
hiworldwzj Aug 23, 2026
f5cee6b
Return decode request splits from overlap prep
hiworldwzj Aug 23, 2026
6514221
Split DP overlap MTP acceptance state
hiworldwzj Aug 23, 2026
327ed2b
Align MTP memory reservation across ranks
hiworldwzj Aug 23, 2026
86f7239
fix: share DFlash hidden KV commit path
shihaobai Aug 24, 2026
9cbc9c0
chore: update Qwen3.5 DSpark 1P1D launch
shihaobai Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions deploy_dspark_1p1d.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#!/usr/bin/env bash
set -euo pipefail

PORT="${PORT:-16666}"
MODEL_DIR="${MODEL_DIR:-/mnt/afs/models/Qwen3.5-27B}"
DRAFT_MODEL_DIR="${DRAFT_MODEL_DIR:-${draft_model:-}}"
MODEL_NAME="${MODEL_NAME:-sensenova-flash-lite-v41-20260816-fp8-step3k-dspark}"

CPU_CACHE_SIZE="${CPU_CACHE_SIZE:-600}"
CHAT_TEMPLATE="${CHAT_TEMPLATE:-${MODEL_DIR}/chat_template.jinja}"
PD_MASTER_IP="${PD_MASTER_IP:-127.0.0.1}"

# DSpark checkpoint block_size. Prefill and decode must use the same value.
MTP_STEP="${MTP_STEP:-5}"

# DSpark expands each logical decode request into speculative verification rows.
# Start conservatively; raise both values together after checking GPU headroom.
D_MAX_REQ_SIZE="${D_MAX_REQ_SIZE:-16}"
D_GRAPH_MAX_BATCH_SIZE="${D_GRAPH_MAX_BATCH_SIZE:-16}"

if [[ -z "${DRAFT_MODEL_DIR}" ]]; then
echo "DRAFT_MODEL_DIR is required (the DSpark draft checkpoint directory)." >&2
exit 2
fi

export LOADWORKER="${LOADWORKER:-8}"
export LIGHTLLM_TRITON_AUTOTUNE_LEVEL="${LIGHTLLM_TRITON_AUTOTUNE_LEVEL:-1}"
export LIGHTLLM_ANTHROPIC_ENABLE_PDF_PARSING="${LIGHTLLM_ANTHROPIC_ENABLE_PDF_PARSING:-1}"
export LIGHTLLM_LOG_LEVEL="${LIGHTLLM_LOG_LEVEL:-debug}"
export PYTHONUNBUFFERED=1
export LIGHTLLM_PD_SPLIT_MAX_NEW_TOKENS="${LIGHTLLM_PD_SPLIT_MAX_NEW_TOKENS:-4096}"

# Keep same-host PD WebSocket traffic away from HTTP/WebSocket proxies.
export NO_PROXY="${NO_PROXY:+${NO_PROXY},}${PD_MASTER_IP},localhost"
export no_proxy="${NO_PROXY}"

RUN_NAME="${RUN_NAME:-qwen35-dspark-1p1d}"
LOG_DIR="${LOG_ROOT:-/mnt/afs/lightllm-runs}/${RUN_NAME}"
mkdir -p "${LOG_DIR}"

P_COMMON_ARGS=(
--model_dir "${MODEL_DIR}"
--model_name "${MODEL_NAME}"
--graph_max_batch_size 32
--running_max_req_size 32
--mem_fraction 0.75
--max_image_token_count 4096
--max_image_pixels 3686400
--batch_max_tokens 32768
--chunked_prefill_size 16384
--linear_att_cache_size 500
--linear_att_hash_page_size 2048
--linear_att_page_block_num 8
--quant_type fp8w8a8-pt-sgl
--mtp_mode dspark
--mtp_draft_model_dir "${DRAFT_MODEL_DIR}"
--mtp_step "${MTP_STEP}"
--chat_template "${CHAT_TEMPLATE}"
--pd_trans_mode nixl
--pd_kv_page_size 4096
--pd_master_ip "${PD_MASTER_IP}"
--pd_master_port "${PORT}"
--llm_prefill_att_backend fa3 flashqla
)

D_COMMON_ARGS=(
--model_dir "${MODEL_DIR}"
--model_name "${MODEL_NAME}"
--graph_max_batch_size "${D_GRAPH_MAX_BATCH_SIZE}"
--running_max_req_size "${D_MAX_REQ_SIZE}"
--mem_fraction 0.75
--max_image_token_count 4096
--max_image_pixels 3686400
--batch_max_tokens 256
--linear_att_cache_size 500
--quant_type fp8w8a8-pt-sgl
--mtp_mode dspark
--mtp_draft_model_dir "${DRAFT_MODEL_DIR}"
--mtp_step "${MTP_STEP}"
--chat_template "${CHAT_TEMPLATE}"
--pd_trans_mode nixl
--pd_kv_page_size 4096
--pd_master_ip "${PD_MASTER_IP}"
--pd_master_port "${PORT}"
)

PIDS=()

cleanup() {
if ((${#PIDS[@]} > 0)); then
kill -TERM "${PIDS[@]}" 2>/dev/null || true
wait "${PIDS[@]}" 2>/dev/null || true
fi
}

trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

start_prefill() {
local name="$1"
local devices="$2"
local http_port="$3"
local nccl_port="$4"

echo "Starting ${name}: GPUs=${devices}, port=${http_port}"

CUDA_VISIBLE_DEVICES="${devices}" \
python -m lightllm.server.api_server \
"${P_COMMON_ARGS[@]}" \
--run_mode prefill \
--enable_cpu_cache \
--cpu_cache_storage_size "${CPU_CACHE_SIZE}" \
--tp 4 \
--dp 1 \
--visual_dp 4 \
--host 0.0.0.0 \
--port "${http_port}" \
--nccl_port "${nccl_port}" \
>>"${LOG_DIR}/${name}.log" 2>&1 &

PIDS+=("$!")
}

start_decode() {
local name="$1"
local devices="$2"
local http_port="$3"
local nccl_port="$4"

echo "Starting ${name}: GPUs=${devices}, port=${http_port}"

CUDA_VISIBLE_DEVICES="${devices}" \
python -m lightllm.server.api_server \
"${D_COMMON_ARGS[@]}" \
--run_mode decode \
--tp 4 \
--dp 1 \
--visual_dp 4 \
--host 0.0.0.0 \
--port "${http_port}" \
--nccl_port "${nccl_port}" \
>>"${LOG_DIR}/${name}.log" 2>&1 &

PIDS+=("$!")
}

# Single node: Prefill on GPUs 0-3, Decode on GPUs 4-7.
start_prefill p1 "0,1,2,3" 28761 29761
start_decode d1 "4,5,6,7" 28762 29762

# CPU-only PD Master. This is the public service endpoint.
python -m lightllm.server.api_server \
--model_dir "${MODEL_DIR}" \
--model_name "${MODEL_NAME}" \
--run_mode pd_master \
--pd_master_mode 1p1d \
--host 0.0.0.0 \
--port "${PORT}" \
--max_image_token_count 4096 \
--max_image_pixels 3686400 \
--chat_template "${CHAT_TEMPLATE}" \
>>"${LOG_DIR}/pd-master.log" 2>&1 &
PIDS+=("$!")

echo "PD Master is starting at http://${PD_MASTER_IP}:${PORT}"
echo "logs: ${LOG_DIR}"

# A fixed 1P1D deployment is incomplete as soon as any component exits.
if wait -n "${PIDS[@]}"; then
echo "A LightLLM component exited unexpectedly" >&2
else
echo "A LightLLM component failed" >&2
fi
exit 1
55 changes: 46 additions & 9 deletions lightllm/common/basemodel/attention/base_att.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,79 @@
import threading

import torch
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional, TYPE_CHECKING, Tuple, Union, Dict

from lightllm.utils.dist_utils import get_current_device_id
from lightllm.utils.envs_utils import get_env_start_args

if TYPE_CHECKING:
from lightllm.common.basemodel.basemodel import TpPartBaseModel
from lightllm.common.basemodel.infer_struct import InferStateInfo


class BaseAttBackend:
"""
用于创建支持各种不同的AttBackend, 如 fa3, flashinfer, triton 实现等
这个是单列模式, 每种backend只有一个实例
用于创建支持各种不同的AttBackend, 如 fa3, flashinfer, triton 实现等
每个 model 复用一个 backend 实例。
"""

_instances = {}
_workspace_buffers = {}
_workspace_buffer_lock = threading.Lock()

def __new__(cls, *args, **kwargs):
"""
重写__new__方法实现单例模式
Main 和 speculative draft model 可能使用不同的 CUDA graph 上限
和缓存布局,不能只按 backend class 共享实例。
"""
# 检查是否已经有该类的实例
if cls not in cls._instances:
# 创建新实例并存储
model = kwargs.get("model", args[0] if args else None)
instance_key = (cls, model)
if instance_key not in cls._instances:
instance = super().__new__(cls)
cls._instances[cls] = instance
# 返回已有的实例
return cls._instances[cls]
cls._instances[instance_key] = instance
return cls._instances[instance_key]

def __init__(self, model: "TpPartBaseModel"):
self.model = model

@staticmethod
def get_gpu_workspace_buffer(key_name: str, workspace_size: int, dtype: torch.dtype = torch.int8) -> torch.Tensor:
"""Return a process-local workspace shared by key name and CUDA device."""
if not key_name:
raise ValueError("workspace key_name must not be empty")
if workspace_size <= 0:
raise ValueError(f"workspace_size must be positive, got {workspace_size}")

device_id = get_current_device_id()
buffer_key = (device_id, key_name, workspace_size, dtype)
with BaseAttBackend._workspace_buffer_lock:
workspace_buffer = BaseAttBackend._workspace_buffers.get(buffer_key)
if workspace_buffer is None:
workspace_buffer = torch.empty(workspace_size, dtype=dtype, device=device_id)
BaseAttBackend._workspace_buffers[buffer_key] = workspace_buffer
return workspace_buffer

def create_att_prefill_state(self) -> "BasePrefillAttState":
raise NotImplementedError("not impl")

def create_att_decode_state(self) -> "BaseDecodeAttState":
raise NotImplementedError("not impl")

def uses_dynamic_spec_verify_layout(self) -> bool:
args = get_env_start_args()
draft_step = self.model.mtp_manager.get_decode_draft_step(self.model.is_mtp_draft_model)
is_main_model = not self.model.is_mtp_draft_model
has_decode_draft_step = draft_step > 0
dynamic_verify_enabled = args.mtp_dynamic_verify
return is_main_model and has_decode_draft_step and dynamic_verify_enabled

def uses_causal_attention(self) -> bool:
args = get_env_start_args()
is_parallel_block_draft = self.model.is_mtp_draft_model and args.mtp_mode in ("dspark", "dflash")
return not is_parallel_block_draft

def _find_layer_index(
self, k: torch.Tensor, v: torch.Tensor, att_state: Union["BasePrefillAttState", "BaseDecodeAttState"]
) -> int:
Expand Down
Loading
Loading