Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11e5ba6e8f | ||
|
|
fb341f8de5 |
@@ -12,12 +12,7 @@ name: build-sglang-image
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [dsv41-pd, dsv41-pd-visioncp]
|
branches: [dsv41-pd]
|
||||||
# compose/部署配置 与 workflow 自身的改动不触发镜像构建(省 runner 与推送带宽)。
|
|
||||||
# 改了 workflow 想重建镜像时,需伴随任意代码改动或手动触发。
|
|
||||||
paths-ignore:
|
|
||||||
- 'deploy/**'
|
|
||||||
- '.gitea/**'
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# 直接写死 Gitea 自带 registry(vars context 在该实例上求值异常会导致回退 docker.io)
|
# 直接写死 Gitea 自带 registry(vars context 在该实例上求值异常会导致回退 docker.io)
|
||||||
@@ -49,9 +44,7 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
file: Dockerfile.gitea
|
file: Dockerfile.gitea
|
||||||
push: true
|
push: true
|
||||||
# cache-from: type=registry
|
|
||||||
# cache-to: type=registry,mode=max
|
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.tag }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.tag }}
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-latest
|
||||||
|
# 注意:type=gha 缓存在本实例的 runner 上会 404(cache server 未配),勿加回
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
# 优化版(2026-09-24):解决清华源限流下每次构建重下 torch 的问题。
|
|
||||||
# 要点:
|
|
||||||
# 1. pyproject build-system.requires 含 torch==2.13.0,pip 隔离构建环境每次都重下 ~6GB。
|
|
||||||
# 基底镜像已装 torch 2.13 → 用 --no-build-isolation 复用,构建环境零下载。
|
|
||||||
# 2. 基底缺 setuptools-scm(版本打戳要用),单层预装 + pip cache mount,只下载一次。
|
|
||||||
# 3. RUN 的 pip cache mount 持久化在宿主机,依赖解析命中的包不再重复下载。
|
|
||||||
FROM uhub.service.ucloud.cn/umirror/sglang:dev-dsv41
|
|
||||||
|
|
||||||
ARG PIP_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple
|
|
||||||
ENV PIP_INDEX_URL=${PIP_INDEX}
|
|
||||||
|
|
||||||
# 构建后端(pyproject build-system.requires,torch 除外——基底已有)
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
||||||
pip install "setuptools>=61" "setuptools-scm>=8" "setuptools-rust>=1.11" wheel
|
|
||||||
|
|
||||||
# 整个源码树(含 .git,用于 setuptools-scm 版本打戳)
|
|
||||||
COPY sglang/ /sgl-workspace/sglang/
|
|
||||||
|
|
||||||
# editable 安装,全量依赖解析(pyproject.toml 变化时走这个)
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
||||||
pip install --no-build-isolation -e /sgl-workspace/sglang/python
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# fast 路径:python/pyproject.toml 未变化时使用(build.sh 自动判断)。
|
|
||||||
# --no-deps 跳过全部依赖解析(连 index 元数据请求都省掉),纯源码迭代秒级完成。
|
|
||||||
# 依赖有变化时必须走 Dockerfile 全量路径(build.sh 按 pyproject sha256 自动切换)。
|
|
||||||
FROM uhub.service.ucloud.cn/umirror/sglang:dev-dsv41
|
|
||||||
|
|
||||||
ARG PIP_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple
|
|
||||||
ENV PIP_INDEX_URL=${PIP_INDEX}
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
||||||
pip install "setuptools>=61" "setuptools-scm>=8" "setuptools-rust>=1.11" wheel
|
|
||||||
|
|
||||||
COPY sglang/ /sgl-workspace/sglang/
|
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
||||||
pip install --no-deps --no-build-isolation -e /sgl-workspace/sglang/python
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# 用法: /data/ymk/build/build.sh [tag]
|
|
||||||
# 默认 tag: ymkymx/sglang:<分支>-<sha9>-local-<UTC构建日期时间>(命名规则见 AGENTS.md)
|
|
||||||
# 另打 <分支>-latest-local 别名。
|
|
||||||
#
|
|
||||||
# 依赖路径自动选择:
|
|
||||||
# python/pyproject.toml 的 sha256 与上次成功构建一致 → Dockerfile.fast(--no-deps,秒级)
|
|
||||||
# 不一致(或 FULL=1)→ Dockerfile 全量依赖解析,成功后记录新 hash
|
|
||||||
set -euo pipefail
|
|
||||||
cd /data/ymk
|
|
||||||
SHA=$(git -C sglang rev-parse --short=9 HEAD)
|
|
||||||
BR=$(git -C sglang rev-parse --abbrev-ref HEAD)
|
|
||||||
DT=$(date -u +%Y%m%d-%H%M)
|
|
||||||
TAG=${1:-ymkymx/sglang:$BR-$SHA-local-$DT}
|
|
||||||
|
|
||||||
HASH_FILE=build/.last_pyproject_sha256
|
|
||||||
CUR=$(sha256sum sglang/python/pyproject.toml | cut -d' ' -f1)
|
|
||||||
PREV=$(cat "$HASH_FILE" 2>/dev/null || echo none)
|
|
||||||
|
|
||||||
DOCKERFILE=build/Dockerfile
|
|
||||||
if [ "$CUR" = "$PREV" ] && [ "${FULL:-0}" != "1" ]; then
|
|
||||||
DOCKERFILE=build/Dockerfile.fast
|
|
||||||
echo "== pyproject 未变,走 fast 路径(--no-deps)"
|
|
||||||
else
|
|
||||||
echo "== pyproject 有变化或 FULL=1,走全量依赖解析"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "== building $TAG from sglang@$(git -C sglang log --oneline -1) [$DOCKERFILE]"
|
|
||||||
docker build -f "$DOCKERFILE" -t "$TAG" .
|
|
||||||
# 构建成功才记录 hash / 打别名
|
|
||||||
echo "$CUR" > "$HASH_FILE"
|
|
||||||
docker tag "$TAG" "ymkymx/sglang:$BR-latest-local"
|
|
||||||
echo "== done: $TAG (别名 $BR-latest-local)"
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# B300 ds41 部署 compose 档案
|
|
||||||
|
|
||||||
b300-01 上 DeepSeek-V4.1-Flash 各部署方案的 docker compose 存档。
|
|
||||||
**本目录是 source of truth**;b300 上的运行目录 `/data/ymk/ds41/` 是工作副本。
|
|
||||||
|
|
||||||
方案说明、参数矩阵、特殊 env、已知坑见飞书部署手册(组内共享):
|
|
||||||
《B300 sglang 部署手册》 https://u04wb5irxz.feishu.cn/docx/FOi8dbnybodHr0xIfkPcQ6gtnRx
|
|
||||||
|
|
||||||
## 同步流程
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 本机(D:\B300\sglang)
|
|
||||||
git add deploy/ && git commit -m "deploy: ..."
|
|
||||||
git push origin dsv41-pd-visioncp # Gitea(paths-ignore,不触发镜像构建)
|
|
||||||
git push b300 dsv41-pd-visioncp # b300 裸仓库
|
|
||||||
|
|
||||||
# b300-01
|
|
||||||
git -C /data/ymk/sglang pull # deploy/ 出现在 /data/ymk/sglang/deploy/b300-ds41/
|
|
||||||
```
|
|
||||||
|
|
||||||
## CI 说明
|
|
||||||
|
|
||||||
`.gitea/workflows/build-image.yaml` 的 push 触发器带 `paths-ignore: ['deploy/**', '.gitea/**']`,
|
|
||||||
改本目录不会触发镜像构建。注意:workflow 自身的改动也不再自动触发,需要重建镜像时
|
|
||||||
伴随代码改动 push 或手动触发。
|
|
||||||
|
|
||||||
## 目录规则
|
|
||||||
|
|
||||||
- 命名:`dockerserve-<拓扑>-<特性>-<卡位>.yml`(如 `-b4` = 后 4 卡)
|
|
||||||
- 退役文件不要留在主目录:移入 `archive-YYYYMMDD/`(b300 侧同样执行)
|
|
||||||
- 禁止提交 `.bak` 备份文件
|
|
||||||
- `mooncake-store.json` 是 hicache L3 mooncake store 配置,被
|
|
||||||
`dockerserve-pd2-p-r1/r2.yml` 通过 `SGLANG_HICACHE_MOONCAKE_CONFIG_PATH` 引用
|
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
# 3x cp2-P + 1x dp2-D PD 分离 + L3 mooncake 互联缓存 + engram host table
|
|
||||||
# 2026-09-23 实验;基线见 archive-20260923/ 与 D:\B300\experiments\3cp2-pd\baseline-20260923.md
|
|
||||||
# GPU: P1=0,1 P2=2,3 P3=4,5 D=6,7
|
|
||||||
# 端口: P1=30000 P2=30010 P3=30020 D=30001 router=30002
|
|
||||||
# bootstrap: P1=8998 P2=8999 P3=9000 D=9001
|
|
||||||
x-sglang-common: &sglang-common
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
x-p-environment: &p-environment
|
|
||||||
SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE: "1"
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: static
|
|
||||||
MC_INTRANODE_NVLINK: "true"
|
|
||||||
MC_INTRA_NVLINK: "true"
|
|
||||||
SGLANG_MOONCAKE_SEND_AUX_TCP: "1"
|
|
||||||
SGLANG_HICACHE_MOONCAKE_CONFIG_PATH: /data/ymk/ds41/mooncake-store.json
|
|
||||||
SGLANG_DISAGGREGATION_QUEUE_SIZE: "16"
|
|
||||||
SGLANG_DISAGGREGATION_THREAD_POOL_SIZE: "32"
|
|
||||||
|
|
||||||
services:
|
|
||||||
p1:
|
|
||||||
<<: *sglang-common
|
|
||||||
container_name: ds41-cp2-p1
|
|
||||||
environment:
|
|
||||||
<<: *p-environment
|
|
||||||
CUDA_VISIBLE_DEVICES: "0,1"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30000
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--disaggregation-bootstrap-port 8998
|
|
||||||
|
|
||||||
p2:
|
|
||||||
<<: *sglang-common
|
|
||||||
container_name: ds41-cp2-p2
|
|
||||||
environment:
|
|
||||||
<<: *p-environment
|
|
||||||
CUDA_VISIBLE_DEVICES: "2,3"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30010
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--disaggregation-bootstrap-port 8999
|
|
||||||
|
|
||||||
p3:
|
|
||||||
<<: *sglang-common
|
|
||||||
container_name: ds41-cp2-p3
|
|
||||||
environment:
|
|
||||||
<<: *p-environment
|
|
||||||
CUDA_VISIBLE_DEVICES: "4,5"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30020
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--disaggregation-bootstrap-port 9000
|
|
||||||
|
|
||||||
d:
|
|
||||||
<<: *sglang-common
|
|
||||||
container_name: ds41-cp2-d
|
|
||||||
environment:
|
|
||||||
SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE: "1"
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: static
|
|
||||||
MC_INTRANODE_NVLINK: "true"
|
|
||||||
MC_INTRA_NVLINK: "true"
|
|
||||||
SGLANG_MOONCAKE_SEND_AUX_TCP: "1"
|
|
||||||
SGLANG_DISAGGREGATION_QUEUE_SIZE: "16"
|
|
||||||
SGLANG_DISAGGREGATION_THREAD_POOL_SIZE: "32"
|
|
||||||
CUDA_VISIBLE_DEVICES: "6,7"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2 --dp-size 2
|
|
||||||
--enable-dp-attention --enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.80
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30001
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--disaggregation-mode decode
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--disaggregation-bootstrap-port 9001
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-sglang-b4
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30001:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
- PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.60
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--dp-size 4
|
|
||||||
--enable-dp-attention
|
|
||||||
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-sglang-b4
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30001:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
- PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.60
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
|
|
||||||
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-sglang-b4
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30001:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
# 4×cp2 独立实例(非 PD)+ hicache L3(mooncake) + dspark + engram host table 卸载(2026-09-23 晚)
|
|
||||||
# 用户指定组合:4 cp2 hicache l3 dspark roundrobin loadbalance engram offload
|
|
||||||
# 每实例:tp2 ep2 + interleave CP2 + dspark b5 + hicache L3 write_through(size 0) + engram host table
|
|
||||||
# (tp2 权重必须靠 engram 卸载才放得下,见 goals-track G1.9 反转)
|
|
||||||
# GPU: a=0,1 b=2,3 c=4,5 d=6,7;端口: 30000/30010/30020/30030;rr router=30002
|
|
||||||
# 参考:dockerserve-cpdspark-l3.yml(hicache 参数)、dockerserve-3cp2-pd.yml(cp2/engram 参数)
|
|
||||||
x-common: &common
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
# 热补丁(2026-09-23):CP 对称 idle 检查,修 health-check × hicache drain 死锁
|
|
||||||
# 源文件:/data/ymk/sglang(dsv41-pd-visioncp 分支工作区已改);补丁脚本见
|
|
||||||
# D:\B300\experiments\cp2x4\patch_healthcheck_cp_idle.py
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
environment: &env
|
|
||||||
SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE: "1"
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: static
|
|
||||||
MC_MS_AUTO_DISC: "0"
|
|
||||||
MOONCAKE_MASTER: 127.0.0.1:50051
|
|
||||||
MOONCAKE_TE_META_DATA_SERVER: P2PHANDSHAKE
|
|
||||||
MOONCAKE_PROTOCOL: tcp
|
|
||||||
MOONCAKE_GLOBAL_SEGMENT_SIZE: 300gb
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
services:
|
|
||||||
a:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-cp2-a
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "0,1"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30000
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
b:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-cp2-b
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "2,3"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30010
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
c:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-cp2-c
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "4,5"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30020
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
d:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-cp2-d2
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "6,7"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30030
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# cp8 单机非 PD 测试(2026-09-23 晚)
|
|
||||||
# 背景:dp8 单机 dspark 健康但长上下文 prefill 结构性慢(单请求只落 1 rank),
|
|
||||||
# 换 cp8(tp8 + interleave prefill CP8,单请求 prefill 切到 8 卡)对照。
|
|
||||||
# 关 engram、无 hicache L3、无 PD。cp+dspark 无 replay 是已知健康组合
|
|
||||||
# (cp4+dspark+replay 三元组必崩,本配置不开 replay)。
|
|
||||||
# GPU 0-7,端口 30000,容器 ds41-cp8,project cp8
|
|
||||||
services:
|
|
||||||
cp8:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-cp8
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
environment:
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: "static"
|
|
||||||
CUDA_VISIBLE_DEVICES: "0,1,2,3,4,5,6,7"
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 8 --ep-size 8
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--mem-fraction-static 0.80
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30000
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-ddf520763-local-20260923-0536
|
|
||||||
container_name: ds41-cpdspark-l3-b
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
- MC_MS_AUTO_DISC=0
|
|
||||||
- MOONCAKE_MASTER=127.0.0.1:50051
|
|
||||||
- MOONCAKE_TE_META_DATA_SERVER=P2PHANDSHAKE
|
|
||||||
- MOONCAKE_PROTOCOL=tcp
|
|
||||||
- MOONCAKE_GLOBAL_SEGMENT_SIZE=400gb
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4 --ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30001
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-ddf520763-local-20260923-0536
|
|
||||||
container_name: ds41-cpdspark-l3-b
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
- MC_MS_AUTO_DISC=0
|
|
||||||
- MOONCAKE_MASTER=127.0.0.1:50051
|
|
||||||
- MOONCAKE_TE_META_DATA_SERVER=P2PHANDSHAKE
|
|
||||||
- MOONCAKE_PROTOCOL=tcp
|
|
||||||
- MOONCAKE_GLOBAL_SEGMENT_SIZE=400gb
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4 --ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30001
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-ddf520763-local-20260923-0536
|
|
||||||
container_name: ds41-cpdspark-l3-a
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
- MC_MS_AUTO_DISC=0
|
|
||||||
- MOONCAKE_MASTER=127.0.0.1:50051
|
|
||||||
- MOONCAKE_TE_META_DATA_SERVER=P2PHANDSHAKE
|
|
||||||
- MOONCAKE_PROTOCOL=tcp
|
|
||||||
- MOONCAKE_GLOBAL_SEGMENT_SIZE=400gb
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4 --ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30000
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-ddf520763-local-20260923-0536
|
|
||||||
container_name: ds41-cpdspark-l3-a
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
- MC_MS_AUTO_DISC=0
|
|
||||||
- MOONCAKE_MASTER=127.0.0.1:50051
|
|
||||||
- MOONCAKE_TE_META_DATA_SERVER=P2PHANDSHAKE
|
|
||||||
- MOONCAKE_PROTOCOL=tcp
|
|
||||||
- MOONCAKE_GLOBAL_SEGMENT_SIZE=400gb
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4 --ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30000
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp --cp-strategy interleave
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-92632a60b-20260922-2100
|
|
||||||
container_name: ds41-cpdspark-nr-b4
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30001:30001"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-92632a60b-20260922-2100
|
|
||||||
container_name: ds41-cpdspark-nr
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-cpdspark
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# dp2 对照(2026-09-24 上午):验证 dp2(dp-attention)下 dspark 是否正常。
|
|
||||||
# 与 dockerserve-tp2.yml 逐参数对齐,唯一差异 = 加 --dp-size 2 --enable-dp-attention --enable-dp-lm-head。
|
|
||||||
# GPU 6-7,端口 30030 直连。镜像/补丁挂载/L3/engram/tok8 全部相同。
|
|
||||||
# 注:dp+dspark 不能开 --enable-decoder-swa-bounded-replay(本配置本来就没开)。
|
|
||||||
x-common: &common
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
environment: &env
|
|
||||||
SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE: "1"
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: static
|
|
||||||
MC_MS_AUTO_DISC: "0"
|
|
||||||
MOONCAKE_MASTER: 127.0.0.1:50051
|
|
||||||
MOONCAKE_TE_META_DATA_SERVER: P2PHANDSHAKE
|
|
||||||
MOONCAKE_PROTOCOL: tcp
|
|
||||||
MOONCAKE_GLOBAL_SEGMENT_SIZE: 300gb
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
services:
|
|
||||||
dp2:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-dp2
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "6,7"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--dp-size 2 --enable-dp-attention --enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30030
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-dp4test
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# dp8+tp8 单机非 PD 对照测试(2026-09-23 晚)
|
|
||||||
# 背景:3cp2+dp2 PD 部署 dspark accept 回归(32k ctx accept len 3.14→1.31,
|
|
||||||
# 见 experiments/3cp2-pd/bench-20260923.md「未决问题」)。本配置退回单机验证
|
|
||||||
# dspark 健康度:engram host table 关闭、无 hicache L3、无 PD、无 mooncake。
|
|
||||||
# 参数基准:dockerserve-3cp2-pd.yml 的 d 服务(dp 路径),去掉 PD/L3/engram 相关。
|
|
||||||
# GPU 0-7,端口 30000,容器 ds41-dp8,project dp8
|
|
||||||
services:
|
|
||||||
dp8:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-dp8
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
environment:
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: "static"
|
|
||||||
CUDA_VISIBLE_DEVICES: "0,1,2,3,4,5,6,7"
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 8 --ep-size 8 --dp-size 8
|
|
||||||
--enable-dp-attention --enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.80
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30000
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-prefill
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2.5
|
|
||||||
--hicache-write-policy write_back
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--optimistic-prefill-attempts 4
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd-decode
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--dp-size 4
|
|
||||||
--enable-dp-attention
|
|
||||||
--enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30001
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--disaggregation-mode decode
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-ddf520763-local-20260923-0536
|
|
||||||
container_name: ds41-pd-decode
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5,6,7
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--dp-size 4
|
|
||||||
--enable-dp-attention
|
|
||||||
--enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30001
|
|
||||||
--enable-cache-report
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--disaggregation-mode decode
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-c74a4037f-20260921-1300
|
|
||||||
container_name: ds41-pd-prefill-dp
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--dp-size 4
|
|
||||||
--enable-dp-attention
|
|
||||||
--enable-dp-lm-head
|
|
||||||
--load-balance-method total_tokens
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30010
|
|
||||||
--enable-cache-report
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2.5
|
|
||||||
--hicache-write-policy write_back
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-bootstrap-port 8918
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd-prefill
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2.5
|
|
||||||
--hicache-write-policy write_back
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-ddf520763-local-20260923-0536
|
|
||||||
container_name: ds41-pd-prefill
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2.5
|
|
||||||
--hicache-write-policy write_back
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# PD2 二分 Round 2 D 侧(2026-09-24):干净 D + 嫌疑项②
|
|
||||||
# SGLANG_DISAGGREGATION_QUEUE_SIZE=16 + SGLANG_DISAGGREGATION_THREAD_POOL_SIZE=32
|
|
||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd2-decode
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=6,7
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
- SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE=1
|
|
||||||
- SGLANG_DISAGGREGATION_QUEUE_SIZE=16
|
|
||||||
- SGLANG_DISAGGREGATION_THREAD_POOL_SIZE=32
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2
|
|
||||||
--ep-size 2
|
|
||||||
--dp-size 2
|
|
||||||
--enable-dp-attention
|
|
||||||
--enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30030
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--disaggregation-mode decode
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# PD 干净对照实验 D 节点(2026-09-24 上午):dp2 decode,配 dockerserve-pd2-p.yml 使用。
|
|
||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd2-decode
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=6,7
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
- SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2
|
|
||||||
--ep-size 2
|
|
||||||
--dp-size 2
|
|
||||||
--enable-dp-attention
|
|
||||||
--enable-dp-lm-head
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30030
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--disaggregation-mode decode
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# PD2 二分 Round 1(2026-09-24):干净基线 + 嫌疑项①「P 侧 L3 hicache 块 + mooncake-store.json」
|
|
||||||
# 相对 dockerserve-pd2-p.yml 的差异:
|
|
||||||
# env 加 SGLANG_HICACHE_MOONCAKE_CONFIG_PATH=/data/ymk/ds41/mooncake-store.json
|
|
||||||
# hicache 参数块换成坏部署同款:page_first_direct + direct + write_through + mooncake +
|
|
||||||
# wait_complete + size 0(替代 write_back L2)
|
|
||||||
# D 侧不变(坏部署 D 本无 L3)。探针:bs16 low_entropy decode 看 accept len。
|
|
||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd2-prefill
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
- SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE=1
|
|
||||||
- SGLANG_HICACHE_MOONCAKE_CONFIG_PATH=/data/ymk/ds41/mooncake-store.json
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2
|
|
||||||
--ep-size 2
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30020
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# PD2 二分 Round 2 P 侧(2026-09-24):R1(L3 块)之上再加嫌疑项②
|
|
||||||
# SGLANG_DISAGGREGATION_QUEUE_SIZE=16 + SGLANG_DISAGGREGATION_THREAD_POOL_SIZE=32
|
|
||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd2-prefill
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
- SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE=1
|
|
||||||
- SGLANG_HICACHE_MOONCAKE_CONFIG_PATH=/data/ymk/ds41/mooncake-store.json
|
|
||||||
- SGLANG_DISAGGREGATION_QUEUE_SIZE=16
|
|
||||||
- SGLANG_DISAGGREGATION_THREAD_POOL_SIZE=32
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2
|
|
||||||
--ep-size 2
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30020
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# PD 干净对照实验(2026-09-24 上午):验证「cp2-P → dp2-D」传输路径下 dspark 是否正常。
|
|
||||||
# 用户疑问:单机六形态健康不等于 PD 链路健康,可能两边传输没对齐。
|
|
||||||
# 以已验证可用的 dockerserve-pd-{p,d}-vision.yml 为底,缩到 2+2 卡;P 加 engram host table
|
|
||||||
# (2 卡权重放不下,见 G1.9)。P=GPU4-5 端口 30020,D=GPU6-7 端口 30030,mini_lb=30004。
|
|
||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
container_name: ds41-pd2-prefill
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
pid: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=4,5
|
|
||||||
- SGLANG_RAGGED_VERIFY_MODE=static
|
|
||||||
- MC_INTRANODE_NVLINK=true
|
|
||||||
- MC_INTRA_NVLINK=true
|
|
||||||
- SGLANG_MOONCAKE_SEND_AUX_TCP=1
|
|
||||||
- SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE=1
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2
|
|
||||||
--ep-size 2
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30020
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2.5
|
|
||||||
--hicache-write-policy write_back
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--disaggregation-mode prefill
|
|
||||||
--disaggregation-transfer-backend mooncake
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-replay-off
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: ymkymx/sglang:main-ee5fcdf0d-20260920-0142
|
|
||||||
container_name: ds41-replay-on
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
environment:
|
|
||||||
- CUDA_VISIBLE_DEVICES=0,1,2,3
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--speculative-algorithm DSPARK
|
|
||||||
--speculative-dspark-block-size 5
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
# 纯 tp2 单实例对照(2026-09-24 早):与 dockerserve-cp2x4.yml 逐参数对齐,唯一差异 = 去掉
|
|
||||||
# --enable-prefill-cp --cp-strategy interleave(即无 CP),用于测「tp2 vs cp2」的 prefill 效率差。
|
|
||||||
# GPU 4-5(a)/6-7(b),端口 30020/30030;2×tp2 聚合经 rr router 30003。
|
|
||||||
# 镜像/补丁挂载/L3/engram/tok8 全部与 cp2x4 相同。
|
|
||||||
x-common: &common
|
|
||||||
image: ymkymx/sglang:dsv41-pd-visioncp-db7d2cb7d-fix
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
network_mode: host
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
- /data/ymk/cache/sglang:/root/.cache/sglang
|
|
||||||
# 与 cp2x4 保持同一份 scheduler.py(含未 commit 的 CP idle 补丁),保证唯一变量是 CP 开关
|
|
||||||
- /data/ymk/sglang/python/sglang/srt/managers/scheduler.py:/sgl-workspace/sglang/python/sglang/srt/managers/scheduler.py
|
|
||||||
environment: &env
|
|
||||||
SGLANG_ENABLE_DSV41_ENGRAM_HOST_TABLE: "1"
|
|
||||||
SGLANG_RAGGED_VERIFY_MODE: static
|
|
||||||
MC_MS_AUTO_DISC: "0"
|
|
||||||
MOONCAKE_MASTER: 127.0.0.1:50051
|
|
||||||
MOONCAKE_TE_META_DATA_SERVER: P2PHANDSHAKE
|
|
||||||
MOONCAKE_PROTOCOL: tcp
|
|
||||||
MOONCAKE_GLOBAL_SEGMENT_SIZE: 300gb
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
services:
|
|
||||||
tp2:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-tp2
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "4,5"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30020
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
b:
|
|
||||||
<<: *common
|
|
||||||
container_name: ds41-tp2-b
|
|
||||||
environment:
|
|
||||||
<<: *env
|
|
||||||
CUDA_VISIBLE_DEVICES: "6,7"
|
|
||||||
command: >
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 2 --ep-size 2
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--cuda-graph-max-bs-decode 32
|
|
||||||
--reasoning-parser auto --tool-call-parser auto
|
|
||||||
--default-chat-template-kwargs '{"thinking": true, "reasoning_effort": "high"}'
|
|
||||||
--max-running-requests 64
|
|
||||||
--tokenizer-worker-num 8
|
|
||||||
--host 0.0.0.0 --port 30030
|
|
||||||
--enable-cache-report --enable-metrics
|
|
||||||
--speculative-algorithm DSPARK --speculative-dspark-block-size 5
|
|
||||||
--enable-hierarchical-cache
|
|
||||||
--hicache-ratio 2
|
|
||||||
--hicache-mem-layout page_first_direct
|
|
||||||
--hicache-io-backend direct
|
|
||||||
--hicache-write-policy write_through
|
|
||||||
--hicache-storage-backend mooncake
|
|
||||||
--hicache-storage-prefetch-policy wait_complete
|
|
||||||
--hicache-size 0
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
services:
|
|
||||||
sglang:
|
|
||||||
image: uhub.service.ucloud.cn/umirror/sglang:dev-dsv41
|
|
||||||
shm_size: "32gb"
|
|
||||||
ipc: host
|
|
||||||
privileged: true
|
|
||||||
|
|
||||||
ports:
|
|
||||||
- "30000:30000"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
- /data:/data
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
command: >-
|
|
||||||
sglang serve
|
|
||||||
--trust-remote-code
|
|
||||||
--model-path /data/models/DeepSeek-V4.1-Flash
|
|
||||||
--tp 4
|
|
||||||
--ep-size 4
|
|
||||||
--mem-fraction-static 0.75
|
|
||||||
--attention-backend dsv4
|
|
||||||
--moe-runner-backend flashinfer_mxfp4
|
|
||||||
--enable-decoder-swa-bounded-replay
|
|
||||||
--cuda-graph-max-bs-decode 64
|
|
||||||
--reasoning-parser auto
|
|
||||||
--tool-call-parser auto
|
|
||||||
--max-running-requests 64
|
|
||||||
--host 0.0.0.0
|
|
||||||
--port 30000
|
|
||||||
--enable-cache-report
|
|
||||||
--enable-metrics
|
|
||||||
--enable-prefill-cp
|
|
||||||
--cp-strategy interleave
|
|
||||||
--json-model-override-args '{"vision_n_layers": 0}'
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"master_server_address": "127.0.0.1:50051",
|
|
||||||
"metadata_server": "P2PHANDSHAKE",
|
|
||||||
"global_segment_size": "300gb",
|
|
||||||
"protocol": "tcp"
|
|
||||||
}
|
|
||||||
@@ -181,15 +181,12 @@ def validate_deepseek_v41_features(server_args: ServerArgs) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
cfg = resolving_view(server_args)
|
cfg = resolving_view(server_args)
|
||||||
hf_config = model_config_of(server_args).hf_config
|
if model_config_of(server_args).hf_config.model_type != "deepseek_v41":
|
||||||
if hf_config.model_type != "deepseek_v41":
|
|
||||||
if cfg.enable_encoder_swa_bounded_replay:
|
if cfg.enable_encoder_swa_bounded_replay:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"--enable-encoder-swa-bounded-replay requires DeepSeek-V4.1"
|
"--enable-encoder-swa-bounded-replay requires DeepSeek-V4.1"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
if hf_config.vision_n_layers > 0 and cfg.enable_prefill_cp:
|
|
||||||
_validate_deepseek_v41_vision_prefill_cp(server_args)
|
|
||||||
if cfg.enable_encoder_swa_bounded_replay:
|
if cfg.enable_encoder_swa_bounded_replay:
|
||||||
from sglang.srt.model_executor.cuda_graph_config import Backend
|
from sglang.srt.model_executor.cuda_graph_config import Backend
|
||||||
|
|
||||||
@@ -200,8 +197,7 @@ def validate_deepseek_v41_features(server_args: ServerArgs) -> None:
|
|||||||
cfg.cuda_graph_config.prefill.backend != Backend.DISABLED,
|
cfg.cuda_graph_config.prefill.backend != Backend.DISABLED,
|
||||||
),
|
),
|
||||||
("DP attention", cfg.enable_dp_attention),
|
("DP attention", cfg.enable_dp_attention),
|
||||||
# Prefill CP declares attn_cp_size and DP attention only later.
|
("context parallelism", cfg.attn_cp_size > 1),
|
||||||
("context parallelism", cfg.attn_cp_size > 1 or cfg.enable_prefill_cp),
|
|
||||||
("external cache linker", cfg.enable_unified_cache_external_linker),
|
("external cache linker", cfg.enable_unified_cache_external_linker),
|
||||||
("unified memory", cfg.enable_unified_memory),
|
("unified memory", cfg.enable_unified_memory),
|
||||||
("PD disaggregation", cfg.disaggregation_mode != "null"),
|
("PD disaggregation", cfg.disaggregation_mode != "null"),
|
||||||
@@ -310,40 +306,3 @@ def validate_deepseek_v41_features(server_args: ServerArgs) -> None:
|
|||||||
"--enable-decoder-swa-bounded-replay cannot be combined with "
|
"--enable-decoder-swa-bounded-replay cannot be combined with "
|
||||||
f"{feature} yet; disable one of them."
|
f"{feature} yet; disable one of them."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _validate_deepseek_v41_vision_prefill_cp(server_args: ServerArgs) -> None:
|
|
||||||
from sglang.srt.model_executor.cuda_graph_config import Backend, Phase, with_phase
|
|
||||||
|
|
||||||
cfg = resolving_view(server_args)
|
|
||||||
if cfg.cp_strategy != "interleave":
|
|
||||||
raise ValueError(
|
|
||||||
"DeepSeek-V4.1 vision with prefill CP requires --cp-strategy "
|
|
||||||
f"interleave; got {cfg.cp_strategy!r}."
|
|
||||||
)
|
|
||||||
if cfg.cuda_graph_config.prefill.backend != Backend.DISABLED:
|
|
||||||
# The CP runner merges image features eagerly; no capture path replays it.
|
|
||||||
locked = getattr(server_args, "_cuda_graph_config_locked", set())
|
|
||||||
if (Phase.PREFILL, "backend") in locked:
|
|
||||||
raise ValueError(
|
|
||||||
"DeepSeek-V4.1 vision with prefill CP runs eager prefill; remove "
|
|
||||||
"the explicit prefill CUDA graph backend."
|
|
||||||
)
|
|
||||||
declare_resolution(
|
|
||||||
server_args,
|
|
||||||
"validate_deepseek_v41_features",
|
|
||||||
cuda_graph_config=with_phase(
|
|
||||||
cfg.cuda_graph_config, Phase.PREFILL, backend=Backend.DISABLED
|
|
||||||
),
|
|
||||||
)
|
|
||||||
logger.warning(
|
|
||||||
"Disabling the prefill CUDA graph for DeepSeek-V4.1 vision with prefill CP."
|
|
||||||
)
|
|
||||||
if (
|
|
||||||
str(cfg.speculative_algorithm).upper() == "DSPARK"
|
|
||||||
and cfg.enable_decoder_swa_bounded_replay
|
|
||||||
):
|
|
||||||
raise ValueError(
|
|
||||||
"DeepSeek-V4.1 vision with prefill CP does not support DSpark together "
|
|
||||||
"with --enable-decoder-swa-bounded-replay yet."
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,486 +0,0 @@
|
|||||||
"""One owner rank encodes each image span and broadcasts it to the ranks that
|
|
||||||
run the same prefill chunk; every agreement precedes the payload it guards."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from contextlib import contextmanager
|
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Tuple
|
|
||||||
|
|
||||||
import msgspec
|
|
||||||
import torch
|
|
||||||
|
|
||||||
from sglang.srt.distributed.device_communicators.pynccl_allocator import (
|
|
||||||
disable_symmetric_memory_context,
|
|
||||||
restore_symmetric_memory_context,
|
|
||||||
)
|
|
||||||
from sglang.srt.mem_cache.multimodal_cache import EmbeddingResult, MultiModalStaticCache
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
SpanKey = Tuple[Optional[int], int]
|
|
||||||
SpanEncoder = Callable[[List[Any]], torch.Tensor | List[torch.Tensor]]
|
|
||||||
SpanSignature = Callable[[Any, int], Tuple[Any, ...]]
|
|
||||||
|
|
||||||
LOCAL_HIT = 0
|
|
||||||
OWNER_CACHE_BROADCAST = 1
|
|
||||||
OWNER_ENCODE_BROADCAST = 2
|
|
||||||
|
|
||||||
PHASE_PREPARE = "prepare"
|
|
||||||
PHASE_FEATURES = "features"
|
|
||||||
PHASE_FINALIZE = "finalize"
|
|
||||||
|
|
||||||
|
|
||||||
class MmOwnerProtocolError(RuntimeError):
|
|
||||||
"""Raised with identical text on every group member after a group-agreed failure."""
|
|
||||||
|
|
||||||
|
|
||||||
class ImageSpanRequest(msgspec.Struct, frozen=True):
|
|
||||||
hash: Optional[int]
|
|
||||||
span_len: int
|
|
||||||
item: Any
|
|
||||||
inside_chunk: bool
|
|
||||||
duplicates: List[Any] = []
|
|
||||||
|
|
||||||
|
|
||||||
class ImageSpanKey(msgspec.Struct, frozen=True):
|
|
||||||
hash: Optional[int]
|
|
||||||
span_len: int
|
|
||||||
geometry: Optional[Tuple[Any, ...]]
|
|
||||||
|
|
||||||
|
|
||||||
class RankManifest(msgspec.Struct, frozen=True):
|
|
||||||
rank: int
|
|
||||||
keys: List[ImageSpanKey]
|
|
||||||
cached: List[bool]
|
|
||||||
dtype: str
|
|
||||||
width: int
|
|
||||||
rids: List[str]
|
|
||||||
error: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
class OwnerPlan(msgspec.Struct, frozen=True):
|
|
||||||
actions: List[int]
|
|
||||||
owners: List[int]
|
|
||||||
error: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
class RankStatus(msgspec.Struct, frozen=True):
|
|
||||||
rank: int
|
|
||||||
error: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
def select_owner_group(parallel) -> Optional[Any]:
|
|
||||||
"""The group whose members all execute the same requests, or None when a
|
|
||||||
single rank already encodes every image it sees."""
|
|
||||||
replication = parallel.tp_size // parallel.attn_dp_size
|
|
||||||
if replication <= 1:
|
|
||||||
return None
|
|
||||||
if parallel.attn_cp_size == 1:
|
|
||||||
group = parallel.attn_tp_group
|
|
||||||
elif parallel.attn_dp_size == 1 and parallel.attn_cp_size == parallel.tp_size:
|
|
||||||
group = parallel.attn_cp_group
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
return group if group.world_size == replication else None
|
|
||||||
|
|
||||||
|
|
||||||
def has_owner_span_work(
|
|
||||||
mm_inputs: Sequence[Any],
|
|
||||||
extend_prefix_lens: Sequence[int],
|
|
||||||
extend_seq_lens: Sequence[int],
|
|
||||||
) -> bool:
|
|
||||||
"""Host-side mirror of the per-image scheduling path: does any raw
|
|
||||||
single-span image overlap the chunk on every rank of the group."""
|
|
||||||
for mm_input, prefix_len, extend_len in zip(
|
|
||||||
mm_inputs, extend_prefix_lens, extend_seq_lens
|
|
||||||
):
|
|
||||||
if mm_input is None or extend_len <= 0:
|
|
||||||
continue
|
|
||||||
items = [item for item in mm_input.mm_items if item is not None]
|
|
||||||
if not items or any(
|
|
||||||
item.precomputed_embeddings is not None or len(item.offsets) != 1
|
|
||||||
for item in items
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
for item in items:
|
|
||||||
start, end = item.offsets[0]
|
|
||||||
if end >= prefix_len and start < prefix_len + extend_len:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class MmOwnerSession(msgspec.Struct):
|
|
||||||
group: Any
|
|
||||||
device: Any
|
|
||||||
dtype: Any
|
|
||||||
width: int
|
|
||||||
rids: List[str]
|
|
||||||
signature: Any
|
|
||||||
engaged: bool
|
|
||||||
phase: str = PHASE_PREPARE
|
|
||||||
in_collective: bool = False
|
|
||||||
|
|
||||||
def resolve(
|
|
||||||
self,
|
|
||||||
requests: Sequence[ImageSpanRequest],
|
|
||||||
cache: MultiModalStaticCache,
|
|
||||||
encode: SpanEncoder,
|
|
||||||
) -> Dict[SpanKey, torch.Tensor]:
|
|
||||||
if not self.engaged:
|
|
||||||
raise RuntimeError(
|
|
||||||
"owner protocol reached for a chunk whose host metadata has no image span"
|
|
||||||
)
|
|
||||||
# Owners allocate different amounts than receivers, so none of these
|
|
||||||
# buffers may come out of a symmetric pool.
|
|
||||||
saved_context = disable_symmetric_memory_context()
|
|
||||||
try:
|
|
||||||
return _resolve_owner_features(self, requests, cache, encode)
|
|
||||||
finally:
|
|
||||||
restore_symmetric_memory_context(saved_context)
|
|
||||||
|
|
||||||
def features_ready(self) -> None:
|
|
||||||
self._complete()
|
|
||||||
self.phase = PHASE_FINALIZE
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def uncaptured(self) -> Iterator[None]:
|
|
||||||
# A failure inside a collective leaves the group in an unknown state;
|
|
||||||
# no later exchange may try to agree on it.
|
|
||||||
self.in_collective = True
|
|
||||||
yield
|
|
||||||
self.in_collective = False
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def fence(self) -> Iterator[None]:
|
|
||||||
try:
|
|
||||||
yield
|
|
||||||
except Exception as exc:
|
|
||||||
self._fail(exc)
|
|
||||||
raise
|
|
||||||
self._complete()
|
|
||||||
|
|
||||||
def _fail(self, exc: BaseException) -> None:
|
|
||||||
if (
|
|
||||||
not self.engaged
|
|
||||||
or self.in_collective
|
|
||||||
or isinstance(exc, MmOwnerProtocolError)
|
|
||||||
):
|
|
||||||
raise exc
|
|
||||||
text = _describe(self, self.phase, exc)
|
|
||||||
if self.phase == PHASE_PREPARE:
|
|
||||||
try:
|
|
||||||
_exchange_manifest(self, _manifest(self, [], [], error=text))
|
|
||||||
except MmOwnerProtocolError as agreed:
|
|
||||||
raise agreed from exc
|
|
||||||
_exchange_status(self, text, exc)
|
|
||||||
|
|
||||||
def _complete(self) -> None:
|
|
||||||
if not self.engaged:
|
|
||||||
return
|
|
||||||
if self.phase == PHASE_PREPARE:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"owner protocol {self.phase} completed without a manifest exchange"
|
|
||||||
)
|
|
||||||
error = None
|
|
||||||
cause = None
|
|
||||||
try:
|
|
||||||
_synchronize(self.device)
|
|
||||||
except Exception as exc:
|
|
||||||
cause = exc
|
|
||||||
error = _describe(self, self.phase, exc)
|
|
||||||
_exchange_status(self, error, cause)
|
|
||||||
|
|
||||||
|
|
||||||
def _manifest(
|
|
||||||
session: MmOwnerSession,
|
|
||||||
keys: List[ImageSpanKey],
|
|
||||||
cached: List[bool],
|
|
||||||
error: Optional[str] = None,
|
|
||||||
) -> RankManifest:
|
|
||||||
return RankManifest(
|
|
||||||
rank=session.group.rank_in_group,
|
|
||||||
keys=keys,
|
|
||||||
cached=cached,
|
|
||||||
dtype=str(session.dtype),
|
|
||||||
width=session.width,
|
|
||||||
rids=list(session.rids),
|
|
||||||
error=error,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _exchange_manifest(session: MmOwnerSession, manifest: RankManifest) -> OwnerPlan:
|
|
||||||
group = session.group
|
|
||||||
with session.uncaptured():
|
|
||||||
manifests = group.all_gather_object(manifest)
|
|
||||||
plan = _plan_or_error(session, manifests) if group.rank_in_group == 0 else None
|
|
||||||
plan = group.broadcast_object(plan, src=0)
|
|
||||||
session.phase = PHASE_FEATURES
|
|
||||||
if plan.error is not None:
|
|
||||||
raise MmOwnerProtocolError(plan.error)
|
|
||||||
return plan
|
|
||||||
|
|
||||||
|
|
||||||
def _plan_or_error(session: MmOwnerSession, manifests: List[RankManifest]) -> OwnerPlan:
|
|
||||||
try:
|
|
||||||
return _make_plan(manifests)
|
|
||||||
except Exception as exc:
|
|
||||||
return OwnerPlan(actions=[], owners=[], error=_describe(session, "plan", exc))
|
|
||||||
|
|
||||||
|
|
||||||
def _exchange_status(
|
|
||||||
session: MmOwnerSession, error: Optional[str], cause: Optional[BaseException]
|
|
||||||
) -> None:
|
|
||||||
with session.uncaptured():
|
|
||||||
statuses = session.group.all_gather_object(
|
|
||||||
RankStatus(rank=session.group.rank_in_group, error=error)
|
|
||||||
)
|
|
||||||
_raise_first_error(statuses, cause)
|
|
||||||
|
|
||||||
|
|
||||||
def _resolve_owner_features(
|
|
||||||
session: MmOwnerSession,
|
|
||||||
requests: Sequence[ImageSpanRequest],
|
|
||||||
cache: MultiModalStaticCache,
|
|
||||||
encode: SpanEncoder,
|
|
||||||
) -> Dict[SpanKey, torch.Tensor]:
|
|
||||||
group = session.group
|
|
||||||
features: Dict[SpanKey, torch.Tensor] = {}
|
|
||||||
keys: List[ImageSpanKey] = []
|
|
||||||
cached: List[bool] = []
|
|
||||||
error = None
|
|
||||||
try:
|
|
||||||
keys, cached = _pin_local_cache(session, requests, cache, features)
|
|
||||||
except Exception as exc:
|
|
||||||
error = _describe(session, "manifest", exc)
|
|
||||||
plan = _exchange_manifest(session, _manifest(session, keys, cached, error))
|
|
||||||
|
|
||||||
if all(action == LOCAL_HIT for action in plan.actions):
|
|
||||||
return features
|
|
||||||
|
|
||||||
buffers: Dict[int, torch.Tensor] = {}
|
|
||||||
error = None
|
|
||||||
try:
|
|
||||||
buffers = _prepare_transfers(session, requests, keys, plan, features, encode)
|
|
||||||
_synchronize(session.device)
|
|
||||||
except Exception as exc:
|
|
||||||
error = _describe(session, "encode", exc)
|
|
||||||
_exchange_status(session, error, None)
|
|
||||||
|
|
||||||
with session.uncaptured():
|
|
||||||
for index, (action, owner) in enumerate(zip(plan.actions, plan.owners)):
|
|
||||||
if action != LOCAL_HIT:
|
|
||||||
group.broadcast(buffers[index], src=owner)
|
|
||||||
|
|
||||||
for index, key in enumerate(keys):
|
|
||||||
if plan.actions[index] == LOCAL_HIT:
|
|
||||||
continue
|
|
||||||
span = buffers[index]
|
|
||||||
features[(key.hash, key.span_len)] = span
|
|
||||||
cache.set(key.hash, EmbeddingResult(embedding=span))
|
|
||||||
return features
|
|
||||||
|
|
||||||
|
|
||||||
def _pin_local_cache(
|
|
||||||
session: MmOwnerSession,
|
|
||||||
requests: Sequence[ImageSpanRequest],
|
|
||||||
cache: MultiModalStaticCache,
|
|
||||||
features: Dict[SpanKey, torch.Tensor],
|
|
||||||
) -> Tuple[List[ImageSpanKey], List[bool]]:
|
|
||||||
keys: List[ImageSpanKey] = []
|
|
||||||
cached: List[bool] = []
|
|
||||||
for request in requests:
|
|
||||||
if request.hash is None:
|
|
||||||
raise ValueError(
|
|
||||||
f"image span of {request.span_len} tokens has no content hash"
|
|
||||||
)
|
|
||||||
geometry = session.signature(request.item, request.span_len)
|
|
||||||
for duplicate in request.duplicates:
|
|
||||||
other = session.signature(duplicate, request.span_len)
|
|
||||||
if other != geometry:
|
|
||||||
raise ValueError(
|
|
||||||
f"image hash {request.hash} ({request.span_len} tokens) occurs "
|
|
||||||
f"with different geometry: {geometry} vs {other}"
|
|
||||||
)
|
|
||||||
keys.append(
|
|
||||||
ImageSpanKey(
|
|
||||||
hash=request.hash, span_len=request.span_len, geometry=geometry
|
|
||||||
)
|
|
||||||
)
|
|
||||||
span = _valid_cached_span(session, cache, request)
|
|
||||||
if span is not None:
|
|
||||||
features[(request.hash, request.span_len)] = span
|
|
||||||
cached.append(span is not None)
|
|
||||||
return keys, cached
|
|
||||||
|
|
||||||
|
|
||||||
def _valid_cached_span(
|
|
||||||
session: MmOwnerSession,
|
|
||||||
cache: MultiModalStaticCache,
|
|
||||||
request: ImageSpanRequest,
|
|
||||||
) -> Optional[torch.Tensor]:
|
|
||||||
entry = cache.get_single(request.hash)
|
|
||||||
if entry is None:
|
|
||||||
return None
|
|
||||||
span = entry.embedding
|
|
||||||
if (
|
|
||||||
span.dim() == 2
|
|
||||||
and span.shape[0] == request.span_len
|
|
||||||
and span.shape[1] == session.width
|
|
||||||
and span.dtype == session.dtype
|
|
||||||
and span.device == session.device
|
|
||||||
):
|
|
||||||
return span
|
|
||||||
logger.warning(
|
|
||||||
"Discarding cached multimodal embedding that cannot serve the current "
|
|
||||||
"image span: cache_key=%s expected=(%d, %d, %s) cached=(%s, %s).",
|
|
||||||
request.hash,
|
|
||||||
request.span_len,
|
|
||||||
session.width,
|
|
||||||
session.dtype,
|
|
||||||
tuple(span.shape),
|
|
||||||
span.dtype,
|
|
||||||
)
|
|
||||||
cache.free(request.hash, None)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _make_plan(manifests: List[RankManifest]) -> OwnerPlan:
|
|
||||||
for manifest in manifests:
|
|
||||||
if manifest.error is not None:
|
|
||||||
return OwnerPlan(actions=[], owners=[], error=manifest.error)
|
|
||||||
lead = manifests[0]
|
|
||||||
for manifest in manifests[1:]:
|
|
||||||
if (manifest.keys, manifest.dtype, manifest.width, manifest.rids) != (
|
|
||||||
lead.keys,
|
|
||||||
lead.dtype,
|
|
||||||
lead.width,
|
|
||||||
lead.rids,
|
|
||||||
):
|
|
||||||
return OwnerPlan(
|
|
||||||
actions=[],
|
|
||||||
owners=[],
|
|
||||||
error=(
|
|
||||||
"image manifest mismatch between group ranks 0 and "
|
|
||||||
f"{manifest.rank}: rids={lead.rids} vs {manifest.rids}, "
|
|
||||||
f"keys={lead.keys} vs {manifest.keys}, "
|
|
||||||
f"dtype={lead.dtype} vs {manifest.dtype}, "
|
|
||||||
f"width={lead.width} vs {manifest.width}"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
replication = len(manifests)
|
|
||||||
actions: List[int] = []
|
|
||||||
owners: List[int] = []
|
|
||||||
for index, key in enumerate(lead.keys):
|
|
||||||
owner = key.hash % replication
|
|
||||||
if all(manifest.cached[index] for manifest in manifests):
|
|
||||||
action = LOCAL_HIT
|
|
||||||
elif manifests[owner].cached[index]:
|
|
||||||
action = OWNER_CACHE_BROADCAST
|
|
||||||
else:
|
|
||||||
action = OWNER_ENCODE_BROADCAST
|
|
||||||
actions.append(action)
|
|
||||||
owners.append(owner)
|
|
||||||
return OwnerPlan(actions=actions, owners=owners)
|
|
||||||
|
|
||||||
|
|
||||||
def _prepare_transfers(
|
|
||||||
session: MmOwnerSession,
|
|
||||||
requests: Sequence[ImageSpanRequest],
|
|
||||||
keys: List[ImageSpanKey],
|
|
||||||
plan: OwnerPlan,
|
|
||||||
features: Dict[SpanKey, torch.Tensor],
|
|
||||||
encode: SpanEncoder,
|
|
||||||
) -> Dict[int, torch.Tensor]:
|
|
||||||
rank = session.group.rank_in_group
|
|
||||||
buffers: Dict[int, torch.Tensor] = {}
|
|
||||||
owned: List[int] = []
|
|
||||||
for index, (action, owner) in enumerate(zip(plan.actions, plan.owners)):
|
|
||||||
if action == LOCAL_HIT:
|
|
||||||
continue
|
|
||||||
if owner != rank:
|
|
||||||
try:
|
|
||||||
buffers[index] = _new_span_buffer(session, keys[index])
|
|
||||||
except Exception as exc:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"receive buffer for image hash {keys[index].hash} shape "
|
|
||||||
f"{(keys[index].span_len, session.width)} {session.dtype} "
|
|
||||||
f"failed: {type(exc).__name__}: {exc}"
|
|
||||||
) from exc
|
|
||||||
elif action == OWNER_CACHE_BROADCAST:
|
|
||||||
key = (keys[index].hash, keys[index].span_len)
|
|
||||||
buffers[index] = features[key].contiguous()
|
|
||||||
else:
|
|
||||||
owned.append(index)
|
|
||||||
if owned:
|
|
||||||
owned_hashes = [keys[index].hash for index in owned]
|
|
||||||
try:
|
|
||||||
encoded = encode([requests[index].item for index in owned])
|
|
||||||
except Exception as exc:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"owner encode of image hashes {owned_hashes} failed: "
|
|
||||||
f"{type(exc).__name__}: {exc}"
|
|
||||||
) from exc
|
|
||||||
spans = _split_spans(encoded, [keys[index].span_len for index in owned])
|
|
||||||
for index, span in zip(owned, spans):
|
|
||||||
buffers[index] = _validated_span(session, keys[index], span)
|
|
||||||
return buffers
|
|
||||||
|
|
||||||
|
|
||||||
def _new_span_buffer(session: MmOwnerSession, key: ImageSpanKey) -> torch.Tensor:
|
|
||||||
return torch.empty(
|
|
||||||
(key.span_len, session.width), device=session.device, dtype=session.dtype
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _split_spans(
|
|
||||||
encoded: torch.Tensor | List[torch.Tensor], span_lens: List[int]
|
|
||||||
) -> List[torch.Tensor]:
|
|
||||||
if isinstance(encoded, list):
|
|
||||||
if len(encoded) != len(span_lens):
|
|
||||||
raise ValueError(
|
|
||||||
f"encoder returned {len(encoded)} spans for {len(span_lens)} images"
|
|
||||||
)
|
|
||||||
return [span.reshape(-1, span.shape[-1]) for span in encoded]
|
|
||||||
encoded = encoded.reshape(-1, encoded.shape[-1])
|
|
||||||
if encoded.shape[0] != sum(span_lens):
|
|
||||||
raise ValueError(
|
|
||||||
f"encoder returned {encoded.shape[0]} rows for spans of {span_lens}"
|
|
||||||
)
|
|
||||||
return list(torch.split(encoded, span_lens, dim=0))
|
|
||||||
|
|
||||||
|
|
||||||
def _validated_span(
|
|
||||||
session: MmOwnerSession, key: ImageSpanKey, span: torch.Tensor
|
|
||||||
) -> torch.Tensor:
|
|
||||||
expected = (key.span_len, session.width)
|
|
||||||
if tuple(span.shape) != expected or span.dtype != session.dtype:
|
|
||||||
raise ValueError(
|
|
||||||
f"encoded span for hash={key.hash} has shape {tuple(span.shape)} "
|
|
||||||
f"dtype {span.dtype}; expected {expected} {session.dtype}"
|
|
||||||
)
|
|
||||||
if span.device != session.device:
|
|
||||||
span = span.to(session.device)
|
|
||||||
return span.contiguous()
|
|
||||||
|
|
||||||
|
|
||||||
def _synchronize(device) -> None:
|
|
||||||
if device.type == "cuda":
|
|
||||||
torch.cuda.current_stream(device).synchronize()
|
|
||||||
|
|
||||||
|
|
||||||
def _describe(session: MmOwnerSession, stage: str, exc: BaseException) -> str:
|
|
||||||
return (
|
|
||||||
f"multimodal owner protocol failed during {stage} on group rank "
|
|
||||||
f"{session.group.rank_in_group} (global rank "
|
|
||||||
f"{session.group.ranks[session.group.rank_in_group]}, rids={list(session.rids)}): "
|
|
||||||
f"{type(exc).__name__}: {exc}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _raise_first_error(
|
|
||||||
statuses: List[RankStatus], cause: Optional[BaseException]
|
|
||||||
) -> None:
|
|
||||||
for status in statuses:
|
|
||||||
if status.error is not None:
|
|
||||||
raise MmOwnerProtocolError(status.error) from cause
|
|
||||||
@@ -5,7 +5,6 @@ from typing import Callable, Dict, List, Optional, Tuple
|
|||||||
|
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from sglang.srt.managers.mm_owner_embedding import ImageSpanRequest, MmOwnerSession
|
|
||||||
from sglang.srt.managers.schedule_batch import MultimodalDataItem
|
from sglang.srt.managers.schedule_batch import MultimodalDataItem
|
||||||
from sglang.srt.mem_cache.multimodal_cache import EmbeddingResult, MultiModalStaticCache
|
from sglang.srt.mem_cache.multimodal_cache import EmbeddingResult, MultiModalStaticCache
|
||||||
from sglang.srt.multimodal.evs import EVSEmbeddingResult
|
from sglang.srt.multimodal.evs import EVSEmbeddingResult
|
||||||
@@ -340,24 +339,43 @@ def _batch_encode_per_image_misses(
|
|||||||
unique_misses: Dict[Tuple[Optional[int], int], Tuple[MultimodalDataItem, int]] = {}
|
unique_misses: Dict[Tuple[Optional[int], int], Tuple[MultimodalDataItem, int]] = {}
|
||||||
hash_to_embedding: Dict[Tuple[Optional[int], int], torch.Tensor] = {}
|
hash_to_embedding: Dict[Tuple[Optional[int], int], torch.Tensor] = {}
|
||||||
|
|
||||||
# Phase 1a: collect cache misses over the unique overlapping spans
|
# Phase 1a: find overlapping items per request and collect cache misses
|
||||||
for span in _collect_image_span_requests(per_image_requests):
|
for req_info in per_image_requests:
|
||||||
cache_key = (span.hash, span.span_len)
|
chunk_start = req_info.extend_prefix_len
|
||||||
cached = embedding_cache.get_single(span.hash)
|
chunk_end = chunk_start + req_info.extend_seq_len # exclusive
|
||||||
if cached is not None:
|
overlapping = []
|
||||||
cached_embedding = cached.embedding
|
if req_info.extend_seq_len > 0:
|
||||||
cached_token_count = _embedding_token_count(cached_embedding)
|
for idx, (item, (start, end)) in enumerate(
|
||||||
if cached_token_count == span.span_len:
|
zip(req_info.items, req_info.items_offset)
|
||||||
hash_to_embedding[cache_key] = cached_embedding
|
):
|
||||||
|
if end >= chunk_start and start < chunk_end:
|
||||||
|
overlapping.append((idx, item, start, end))
|
||||||
|
req_info.overlapping = overlapping
|
||||||
|
|
||||||
|
for _idx, item, start, end in overlapping:
|
||||||
|
expected_token_count = end - start + 1
|
||||||
|
cache_key = (item.hash, expected_token_count)
|
||||||
|
if cache_key in hash_to_embedding:
|
||||||
continue
|
continue
|
||||||
_discard_mismatched_cached_embedding(
|
cached = embedding_cache.get_single(item.hash)
|
||||||
span.hash, span.span_len, cached_token_count
|
if cached is not None:
|
||||||
)
|
cached_embedding = cached.embedding
|
||||||
elif (
|
cached_token_count = _embedding_token_count(cached_embedding)
|
||||||
span.inside_chunk and span.item.can_defer_cuda_ipc_feature_reconstruction()
|
if cached_token_count == expected_token_count:
|
||||||
):
|
hash_to_embedding[cache_key] = cached_embedding
|
||||||
span.item.model_specific_data[BORROW_CUDA_IPC_FEATURE_KEY] = True
|
else:
|
||||||
unique_misses[cache_key] = (span.item, span.span_len)
|
_discard_mismatched_cached_embedding(
|
||||||
|
item.hash, expected_token_count, cached_token_count
|
||||||
|
)
|
||||||
|
unique_misses[cache_key] = (item, expected_token_count)
|
||||||
|
elif cache_key not in unique_misses:
|
||||||
|
if (
|
||||||
|
start >= chunk_start
|
||||||
|
and end < chunk_end
|
||||||
|
and item.can_defer_cuda_ipc_feature_reconstruction()
|
||||||
|
):
|
||||||
|
item.model_specific_data[BORROW_CUDA_IPC_FEATURE_KEY] = True
|
||||||
|
unique_misses[cache_key] = (item, expected_token_count)
|
||||||
|
|
||||||
# Phase 1b: single ViT call for all unique cache misses
|
# Phase 1b: single ViT call for all unique cache misses
|
||||||
if unique_misses:
|
if unique_misses:
|
||||||
@@ -394,52 +412,6 @@ def _batch_encode_per_image_misses(
|
|||||||
return hash_to_embedding
|
return hash_to_embedding
|
||||||
|
|
||||||
|
|
||||||
def _collect_image_span_requests(
|
|
||||||
per_image_requests: List[PerImageRequestInfo],
|
|
||||||
) -> List[ImageSpanRequest]:
|
|
||||||
spans: Dict[
|
|
||||||
Tuple[Optional[int], int],
|
|
||||||
Tuple[MultimodalDataItem, bool, List[MultimodalDataItem]],
|
|
||||||
] = {}
|
|
||||||
for req_info in per_image_requests:
|
|
||||||
chunk_start = req_info.extend_prefix_len
|
|
||||||
chunk_end = chunk_start + req_info.extend_seq_len # exclusive
|
|
||||||
overlapping = []
|
|
||||||
if req_info.extend_seq_len > 0:
|
|
||||||
for idx, (item, (start, end)) in enumerate(
|
|
||||||
zip(req_info.items, req_info.items_offset)
|
|
||||||
):
|
|
||||||
if end >= chunk_start and start < chunk_end:
|
|
||||||
overlapping.append((idx, item, start, end))
|
|
||||||
req_info.overlapping = overlapping
|
|
||||||
|
|
||||||
for _idx, item, start, end in overlapping:
|
|
||||||
cache_key = (item.hash, end - start + 1)
|
|
||||||
if cache_key in spans:
|
|
||||||
spans[cache_key][2].append(item)
|
|
||||||
continue
|
|
||||||
spans[cache_key] = (item, start >= chunk_start and end < chunk_end, [])
|
|
||||||
return [
|
|
||||||
ImageSpanRequest(
|
|
||||||
hash=item_hash,
|
|
||||||
span_len=span_len,
|
|
||||||
item=item,
|
|
||||||
inside_chunk=inside_chunk,
|
|
||||||
duplicates=duplicates,
|
|
||||||
)
|
|
||||||
for (item_hash, span_len), (item, inside_chunk, duplicates) in spans.items()
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def _owner_span_encoder(data_embedding_func: DataEmbeddingFunc, device: torch.device):
|
|
||||||
def encode(items: List[MultimodalDataItem]):
|
|
||||||
if not _can_skip_pre_embed_feature_move(data_embedding_func):
|
|
||||||
_move_items_to_device(items, device)
|
|
||||||
return data_embedding_func(items)
|
|
||||||
|
|
||||||
return encode
|
|
||||||
|
|
||||||
|
|
||||||
def _get_chunked_embedding_by_item(
|
def _get_chunked_embedding_by_item(
|
||||||
data_embedding_func: DataEmbeddingFunc,
|
data_embedding_func: DataEmbeddingFunc,
|
||||||
embedding_items_per_req: List[MultimodalDataItem],
|
embedding_items_per_req: List[MultimodalDataItem],
|
||||||
@@ -565,7 +537,6 @@ def _get_chunked_prefill_embedding(
|
|||||||
extend_length: List[int],
|
extend_length: List[int],
|
||||||
items_offset_list: List[List[Tuple[int, int]]],
|
items_offset_list: List[List[Tuple[int, int]]],
|
||||||
input_ids: torch.Tensor,
|
input_ids: torch.Tensor,
|
||||||
mm_owner: Optional[MmOwnerSession] = None,
|
|
||||||
) -> tuple[torch.Tensor | None, torch.Tensor]:
|
) -> tuple[torch.Tensor | None, torch.Tensor]:
|
||||||
"""
|
"""
|
||||||
Chunked prefill embedding: encode items across all requests and extract
|
Chunked prefill embedding: encode items across all requests and extract
|
||||||
@@ -627,22 +598,7 @@ def _get_chunked_prefill_embedding(
|
|||||||
|
|
||||||
# Phase 1: batch encode all per-image cache misses in ONE ViT call
|
# Phase 1: batch encode all per-image cache misses in ONE ViT call
|
||||||
hash_to_embedding: Dict[Tuple[Optional[int], int], torch.Tensor] = {}
|
hash_to_embedding: Dict[Tuple[Optional[int], int], torch.Tensor] = {}
|
||||||
if per_image_requests and mm_owner is not None:
|
if per_image_requests:
|
||||||
# The owner protocol must see every overlapping span before any local
|
|
||||||
# cache filtering: a rank-local hit can never skip a group collective.
|
|
||||||
span_requests = _collect_image_span_requests(per_image_requests)
|
|
||||||
if mm_owner.engaged:
|
|
||||||
hash_to_embedding = mm_owner.resolve(
|
|
||||||
span_requests,
|
|
||||||
cache=embedding_cache,
|
|
||||||
encode=_owner_span_encoder(data_embedding_func, device),
|
|
||||||
)
|
|
||||||
elif span_requests:
|
|
||||||
raise RuntimeError(
|
|
||||||
"owner eligibility saw no image span in this chunk, but "
|
|
||||||
f"scheduling found {len(span_requests)}"
|
|
||||||
)
|
|
||||||
elif per_image_requests:
|
|
||||||
hash_to_embedding = _batch_encode_per_image_misses(
|
hash_to_embedding = _batch_encode_per_image_misses(
|
||||||
data_embedding_func, per_image_requests, device
|
data_embedding_func, per_image_requests, device
|
||||||
)
|
)
|
||||||
@@ -745,7 +701,6 @@ def get_embedding_and_mask(
|
|||||||
prefix_length: List[int],
|
prefix_length: List[int],
|
||||||
extend_length: List[int],
|
extend_length: List[int],
|
||||||
items_offset_list: List[List[Tuple[int, int]]],
|
items_offset_list: List[List[Tuple[int, int]]],
|
||||||
mm_owner: Optional[MmOwnerSession] = None,
|
|
||||||
) -> Tuple[torch.Tensor | None, torch.Tensor | None, torch.Tensor]:
|
) -> Tuple[torch.Tensor | None, torch.Tensor | None, torch.Tensor]:
|
||||||
"""
|
"""
|
||||||
Generate multimodal embeddings and create a mask for identifying their positions in the input sequence.
|
Generate multimodal embeddings and create a mask for identifying their positions in the input sequence.
|
||||||
@@ -786,7 +741,6 @@ def get_embedding_and_mask(
|
|||||||
extend_length,
|
extend_length,
|
||||||
items_offset_list,
|
items_offset_list,
|
||||||
input_ids,
|
input_ids,
|
||||||
mm_owner=mm_owner,
|
|
||||||
)
|
)
|
||||||
if embedding is None:
|
if embedding is None:
|
||||||
return None, None, input_ids
|
return None, None, input_ids
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import pickle
|
|||||||
import sys
|
import sys
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from contextlib import nullcontext
|
|
||||||
from multiprocessing import shared_memory
|
from multiprocessing import shared_memory
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
@@ -25,7 +24,6 @@ from sglang.srt.managers.io_struct import (
|
|||||||
TokenizedEmbeddingReqInput,
|
TokenizedEmbeddingReqInput,
|
||||||
TokenizedGenerateReqInput,
|
TokenizedGenerateReqInput,
|
||||||
)
|
)
|
||||||
from sglang.srt.managers.mm_owner_embedding import MmOwnerSession
|
|
||||||
|
|
||||||
# Preserve the existing initialization import for downstream callers.
|
# Preserve the existing initialization import for downstream callers.
|
||||||
from sglang.srt.managers.mm_schedule import (
|
from sglang.srt.managers.mm_schedule import (
|
||||||
@@ -399,7 +397,6 @@ def embed_mm_inputs(
|
|||||||
data_embedding_func_mapping: Dict[Modality, DataEmbeddingFunc] = None,
|
data_embedding_func_mapping: Dict[Modality, DataEmbeddingFunc] = None,
|
||||||
placeholder_tokens: dict[Modality, List[int]] = None,
|
placeholder_tokens: dict[Modality, List[int]] = None,
|
||||||
use_deepstack: Dict[Modality, bool] = {},
|
use_deepstack: Dict[Modality, bool] = {},
|
||||||
mm_owner: Optional[MmOwnerSession] = None,
|
|
||||||
) -> Optional[torch.Tensor]:
|
) -> Optional[torch.Tensor]:
|
||||||
"""
|
"""
|
||||||
Embed multimodal inputs and integrate them with text token embeddings.
|
Embed multimodal inputs and integrate them with text token embeddings.
|
||||||
@@ -481,7 +478,6 @@ def embed_mm_inputs(
|
|||||||
prefix_length=extend_prefix_lens,
|
prefix_length=extend_prefix_lens,
|
||||||
extend_length=extend_seq_lens,
|
extend_length=extend_seq_lens,
|
||||||
items_offset_list=items_offsets,
|
items_offset_list=items_offsets,
|
||||||
mm_owner=mm_owner,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if use_deepstack.get(modality, None) and embedding is not None:
|
if use_deepstack.get(modality, None) and embedding is not None:
|
||||||
@@ -502,12 +498,7 @@ def embed_mm_inputs(
|
|||||||
# filled with the hash values of the multimodal for the prefix matching in the radix attention.
|
# filled with the hash values of the multimodal for the prefix matching in the radix attention.
|
||||||
# There values are useless because their embeddings will be replaced by vision embeddings anyway.
|
# There values are useless because their embeddings will be replaced by vision embeddings anyway.
|
||||||
input_ids.clamp_(min=0, max=vocab_size - 1)
|
input_ids.clamp_(min=0, max=vocab_size - 1)
|
||||||
if mm_owner is not None:
|
input_embeds = input_embedding(input_ids)
|
||||||
# The text embedding may all-reduce across TP; a rank-local failure in
|
|
||||||
# feature preparation has to be agreed on before any rank enters it.
|
|
||||||
mm_owner.features_ready()
|
|
||||||
with mm_owner.uncaptured() if mm_owner is not None else nullcontext():
|
|
||||||
input_embeds = input_embedding(input_ids)
|
|
||||||
|
|
||||||
# deepstack embedding
|
# deepstack embedding
|
||||||
if use_deepstack:
|
if use_deepstack:
|
||||||
@@ -534,9 +525,7 @@ def embed_mm_inputs(
|
|||||||
_scatter_mm_embedding(dest=input_embeds, mask=mask, src=embedding)
|
_scatter_mm_embedding(dest=input_embeds, mask=mask, src=embedding)
|
||||||
if use_deepstack.get(modality, None):
|
if use_deepstack.get(modality, None):
|
||||||
_scatter_mm_embedding(
|
_scatter_mm_embedding(
|
||||||
dest=input_deepstack_embeds,
|
dest=input_deepstack_embeds, mask=mask, src=deepstack_embeddings[i]
|
||||||
mask=mask,
|
|
||||||
src=deepstack_embeddings[i],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return input_embeds, other_info
|
return input_embeds, other_info
|
||||||
|
|||||||
@@ -1019,15 +1019,6 @@ class PrefillAdder:
|
|||||||
else AddReqResult.CONTINUE
|
else AddReqResult.CONTINUE
|
||||||
)
|
)
|
||||||
|
|
||||||
def can_share_extend_batch(self, req: Req) -> bool:
|
|
||||||
# Token embedding overrides embed the batch's raw input_ids before the
|
|
||||||
# model runs, and that lookup cannot index multimodal placeholder hash IDs.
|
|
||||||
if req.positional_embed_overrides is not None:
|
|
||||||
return all(r.multimodal_inputs is None for r in self.can_run_list)
|
|
||||||
if req.multimodal_inputs is not None:
|
|
||||||
return all(r.positional_embed_overrides is None for r in self.can_run_list)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def add_chunked_req(self, req: Req):
|
def add_chunked_req(self, req: Req):
|
||||||
if self.dllm_config is not None:
|
if self.dllm_config is not None:
|
||||||
_rem_tokens = self._get_dllm_remain_tokens()
|
_rem_tokens = self._get_dllm_remain_tokens()
|
||||||
|
|||||||
@@ -2097,13 +2097,9 @@ class Scheduler(
|
|||||||
vmm_errors = self._materialize_cuda_vmm_inputs(recv_req)
|
vmm_errors = self._materialize_cuda_vmm_inputs(recv_req)
|
||||||
|
|
||||||
# Skip health check when server is busy — ongoing requests already carry health info.
|
# Skip health check when server is busy — ongoing requests already carry health info.
|
||||||
# NOTE: the admit/skip decision must be identical on every CP/TP rank.
|
if is_health_check_generate_req(recv_req) and not self.is_fully_idle(
|
||||||
# is_fully_idle() includes rank-local hicache drain queues, which diverge
|
for_health_check=True
|
||||||
# across ranks right after activity; a divergent decision lets one rank
|
):
|
||||||
# dispatch the health-check generate while others piggyback-skip, breaking
|
|
||||||
# collective ordering (deadlock: one rank blocks in the hicache drain
|
|
||||||
# all_reduce while another waits in the CP request broadcast).
|
|
||||||
if is_health_check_generate_req(recv_req) and not self.is_sched_idle_cp_symmetric():
|
|
||||||
self.return_health_check_ipcs.append(
|
self.return_health_check_ipcs.append(
|
||||||
getattr(recv_req, "http_worker_ipc", None)
|
getattr(recv_req, "http_worker_ipc", None)
|
||||||
)
|
)
|
||||||
@@ -3944,8 +3940,6 @@ class Scheduler(
|
|||||||
for req in self.waiting_queue:
|
for req in self.waiting_queue:
|
||||||
if self.enable_lora and not self.can_schedule_lora_req(req, running_loras):
|
if self.enable_lora and not self.can_schedule_lora_req(req, running_loras):
|
||||||
continue
|
continue
|
||||||
if not adder.can_share_extend_batch(req):
|
|
||||||
break
|
|
||||||
|
|
||||||
running_bs = len(running_batch.reqs)
|
running_bs = len(running_batch.reqs)
|
||||||
candidate_beam_width = (
|
candidate_beam_width = (
|
||||||
@@ -4986,31 +4980,6 @@ class Scheduler(
|
|||||||
else:
|
else:
|
||||||
self.metrics_reporter.record_scheduler_active()
|
self.metrics_reporter.record_scheduler_active()
|
||||||
|
|
||||||
def is_sched_idle_cp_symmetric(self) -> bool:
|
|
||||||
"""Idle check using only state that is identical across CP/TP ranks.
|
|
||||||
|
|
||||||
Request/batch/queue state is collectively maintained (requests arrive
|
|
||||||
via broadcast, batches are collectively scheduled), so every rank
|
|
||||||
computes the same result. Rank-local hicache drain and disagg transfer
|
|
||||||
queues are deliberately excluded: those are exactly the terms that
|
|
||||||
diverge across ranks and caused the CP health-check deadlock
|
|
||||||
(hicache drain all_reduce vs CP request broadcast cross-collective
|
|
||||||
wait, seen on cp2/cp4 + hicache L3 right after router health checks).
|
|
||||||
|
|
||||||
Used only for health-check admission; all other idle logic keeps using
|
|
||||||
is_fully_idle().
|
|
||||||
"""
|
|
||||||
return (
|
|
||||||
self.running_batch.is_empty()
|
|
||||||
and self.chunked_req is None
|
|
||||||
and not self.dllm_manager.any_staging_reqs()
|
|
||||||
and (self.last_batch is None or self.last_batch.is_empty())
|
|
||||||
and (not self.enable_overlap or len(self.result_queue) == 0)
|
|
||||||
and self._pp_microbatches_drained()
|
|
||||||
and len(self.waiting_queue) == 0
|
|
||||||
and len(self.grammar_manager.grammar_queue) == 0
|
|
||||||
)
|
|
||||||
|
|
||||||
def is_fully_idle(self, for_health_check=False) -> bool:
|
def is_fully_idle(self, for_health_check=False) -> bool:
|
||||||
# Health check piggybacks on running requests in process_output.
|
# Health check piggybacks on running requests in process_output.
|
||||||
# Only running_batch + waiting_queue guarantee active GPU processing;
|
# Only running_batch + waiting_queue guarantee active GPU processing;
|
||||||
|
|||||||
@@ -1279,16 +1279,6 @@ class TokenizerManager(TokenizerControlMixin, TokenizerManagerScoreMixin):
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
"encoder SWA replay cannot return cached prompt logprobs"
|
"encoder SWA replay cannot return cached prompt logprobs"
|
||||||
)
|
)
|
||||||
requests_embed_overrides = obj.positional_embed_overrides is not None or (
|
|
||||||
isinstance(obj, EmbeddingReqInput)
|
|
||||||
and obj.embed_overrides is not None
|
|
||||||
and obj.embed_override_token_id is not None
|
|
||||||
)
|
|
||||||
if requests_embed_overrides and obj.contains_mm_input():
|
|
||||||
raise ValueError(
|
|
||||||
"embedding overrides cannot be combined with image, video, or audio "
|
|
||||||
"inputs"
|
|
||||||
)
|
|
||||||
_max_req_len = self.context_len
|
_max_req_len = self.context_len
|
||||||
input_token_num = len(input_ids) if input_ids is not None else 0
|
input_token_num = len(input_ids) if input_ids is not None else 0
|
||||||
input_token_num += self.num_reserved_tokens
|
input_token_num += self.num_reserved_tokens
|
||||||
|
|||||||
@@ -1646,7 +1646,6 @@ class ModelRunner:
|
|||||||
forward_batch.replace_embeds is not None
|
forward_batch.replace_embeds is not None
|
||||||
and forward_batch.replace_positions is not None
|
and forward_batch.replace_positions is not None
|
||||||
):
|
):
|
||||||
misc_utils.validate_replace_embeds_batch(forward_batch)
|
|
||||||
# Token embedding overrides: get base embeddings, scatter replacements
|
# Token embedding overrides: get base embeddings, scatter replacements
|
||||||
if "input_embeds" not in kwargs:
|
if "input_embeds" not in kwargs:
|
||||||
embed_layer = self.model.get_input_embeddings()
|
embed_layer = self.model.get_input_embeddings()
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ from sglang.srt.server_args import CHUNKED_PREFIX_CACHE_SUPPORTED_ATTENTION_BACK
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from sglang.srt.configs.model_config import ModelConfig
|
from sglang.srt.configs.model_config import ModelConfig
|
||||||
from sglang.srt.model_executor.forward_batch_info import ForwardBatch
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -106,24 +105,3 @@ def resolve_pp_proxy_dspark_hidden_size(
|
|||||||
if isinstance(model, _SupportsDSparkPPProxy):
|
if isinstance(model, _SupportsDSparkPPProxy):
|
||||||
return model.get_pp_proxy_dspark_hidden_size()
|
return model.get_pp_proxy_dspark_hidden_size()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def validate_replace_embeds_batch(forward_batch: ForwardBatch) -> None:
|
|
||||||
if forward_batch.mm_inputs is None:
|
|
||||||
return
|
|
||||||
for mm_inputs, prefix_len, extend_len in zip(
|
|
||||||
forward_batch.mm_inputs,
|
|
||||||
forward_batch.extend_prefix_lens_cpu,
|
|
||||||
forward_batch.extend_seq_lens_cpu,
|
|
||||||
):
|
|
||||||
if mm_inputs is None:
|
|
||||||
continue
|
|
||||||
chunk_end = prefix_len + extend_len
|
|
||||||
for item in mm_inputs.mm_items:
|
|
||||||
for start, end in item.offsets or ():
|
|
||||||
if start < chunk_end and end >= prefix_len:
|
|
||||||
# Placeholder rows carry hash IDs the base embedding lookup cannot index.
|
|
||||||
raise ValueError(
|
|
||||||
"Token embedding overrides cannot share an extend batch with "
|
|
||||||
"multimodal placeholders"
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -387,13 +387,12 @@ class EagerRunner(BaseRunner):
|
|||||||
|
|
||||||
input_ids = forward_batch.input_ids
|
input_ids = forward_batch.input_ids
|
||||||
input_embeds = kwargs.get("input_embeds")
|
input_embeds = kwargs.get("input_embeds")
|
||||||
if hasattr(model, "prepare_model_inputs"):
|
# Multimodal spans must be embedded in global token order, before CP
|
||||||
# Multimodal offsets are request-global, so the merge and the
|
# slicing. The model may also normalize image hash IDs for its router.
|
||||||
# placeholder-ID remap must see the full extend layout first.
|
prepare_inputs = getattr(model, "prepare_language_model_inputs", None)
|
||||||
input_ids, input_embeds = model.prepare_model_inputs(
|
if prepare_inputs is not None:
|
||||||
input_ids=input_ids,
|
input_ids, input_embeds = prepare_inputs(
|
||||||
forward_batch=forward_batch,
|
input_ids, forward_batch, input_embeds
|
||||||
input_embeds=input_embeds,
|
|
||||||
)
|
)
|
||||||
if input_embeds is None:
|
if input_embeds is None:
|
||||||
input_embeds = model.get_input_embeddings()(input_ids)
|
input_embeds = model.get_input_embeddings()(input_ids)
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ from sglang.srt.layers.communicator_dsa_cp import (
|
|||||||
dsa_cp_gather_hidden_states,
|
dsa_cp_gather_hidden_states,
|
||||||
dsa_cp_reduce_scatter_hidden_states,
|
dsa_cp_reduce_scatter_hidden_states,
|
||||||
)
|
)
|
||||||
from sglang.srt.layers.cp.base import is_zigzag
|
|
||||||
from sglang.srt.layers.cp.cp_decode_attn_tp import get_cp_decode_attn_tp_ctx
|
from sglang.srt.layers.cp.cp_decode_attn_tp import get_cp_decode_attn_tp_ctx
|
||||||
from sglang.srt.layers.cp.utils import (
|
from sglang.srt.layers.cp.utils import (
|
||||||
cp_gather_full_sequence_states,
|
cp_gather_full_sequence_states,
|
||||||
@@ -121,11 +120,6 @@ from sglang.srt.layers.quantization.mxfp8_input import Mxfp8SwizzledInput
|
|||||||
from sglang.srt.layers.rotary_embedding import get_rope_wrapper
|
from sglang.srt.layers.rotary_embedding import get_rope_wrapper
|
||||||
from sglang.srt.layers.utils import PPMissingLayer, get_layer_id
|
from sglang.srt.layers.utils import PPMissingLayer, get_layer_id
|
||||||
from sglang.srt.layers.vocab_parallel_embedding import VocabParallelEmbedding
|
from sglang.srt.layers.vocab_parallel_embedding import VocabParallelEmbedding
|
||||||
from sglang.srt.managers.mm_owner_embedding import (
|
|
||||||
MmOwnerSession,
|
|
||||||
has_owner_span_work,
|
|
||||||
select_owner_group,
|
|
||||||
)
|
|
||||||
from sglang.srt.managers.mm_utils import (
|
from sglang.srt.managers.mm_utils import (
|
||||||
MultiModalityDataPaddingPatternMultimodalTokens,
|
MultiModalityDataPaddingPatternMultimodalTokens,
|
||||||
embed_mm_inputs,
|
embed_mm_inputs,
|
||||||
@@ -4903,18 +4897,14 @@ class DeepseekV4ForCausalLM(nn.Module):
|
|||||||
and not getattr(config, "language_model_only", False)
|
and not getattr(config, "language_model_only", False)
|
||||||
):
|
):
|
||||||
if (
|
if (
|
||||||
get_parallel().pp_group.world_size != 1
|
get_parallel().attn_cp_size != 1
|
||||||
|
or get_pp_group().world_size != 1
|
||||||
or not _v41_vision_a2a_supported()
|
or not _v41_vision_a2a_supported()
|
||||||
):
|
):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"V4.1 vision supports TP/EP/DP without PP; "
|
"V4.1 vision supports TP/EP/DP without CP or PP; "
|
||||||
"MoE A2A is supported only with MegaMoE on a PD decode node"
|
"MoE A2A is supported only with MegaMoE on a PD decode node"
|
||||||
)
|
)
|
||||||
if get_parallel().attn_cp_size != 1 and (_is_npu or is_zigzag()):
|
|
||||||
raise ValueError(
|
|
||||||
"V4.1 vision context parallelism requires the CUDA interleave "
|
|
||||||
"strategy; NPU and zigzag CP are not supported yet"
|
|
||||||
)
|
|
||||||
|
|
||||||
args = SimpleNamespace(**vars(config), dim=config.hidden_size)
|
args = SimpleNamespace(**vars(config), dim=config.hidden_size)
|
||||||
self.vision = ViT(args)
|
self.vision = ViT(args)
|
||||||
@@ -4922,11 +4912,6 @@ class DeepseekV4ForCausalLM(nn.Module):
|
|||||||
self.image_start = nn.Parameter(torch.empty(config.hidden_size))
|
self.image_start = nn.Parameter(torch.empty(config.hidden_size))
|
||||||
self.image_end = nn.Parameter(torch.empty(config.hidden_size))
|
self.image_end = nn.Parameter(torch.empty(config.hidden_size))
|
||||||
self.image_newline = nn.Parameter(torch.empty(config.hidden_size))
|
self.image_newline = nn.Parameter(torch.empty(config.hidden_size))
|
||||||
self.mm_owner_group = (
|
|
||||||
select_owner_group(get_parallel())
|
|
||||||
if self.vision is not None and _is_cuda
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
self.model = DeepseekV4Model(
|
self.model = DeepseekV4Model(
|
||||||
config, quant_config, prefix=add_prefix("model", prefix)
|
config, quant_config, prefix=add_prefix("model", prefix)
|
||||||
)
|
)
|
||||||
@@ -5061,42 +5046,7 @@ class DeepseekV4ForCausalLM(nn.Module):
|
|||||||
spans.append(span)
|
spans.append(span)
|
||||||
return spans
|
return spans
|
||||||
|
|
||||||
def _image_span_signature(self, item, span_len: int):
|
def _prepare_mm_embeddings(self, input_ids, forward_batch):
|
||||||
h, w = int(item.n_vit_h), int(item.n_vit_w)
|
|
||||||
r = self.config.vision_downsample_ratio
|
|
||||||
expected = len(image_token_types((h + r - 1) // r, (w + r - 1) // r))
|
|
||||||
if expected != span_len:
|
|
||||||
raise ValueError(
|
|
||||||
f"image grid {(h, w)} yields {expected} span tokens, "
|
|
||||||
f"placeholder has {span_len}"
|
|
||||||
)
|
|
||||||
plan = item.model_specific_data.get(GPU_PLAN_KEY)
|
|
||||||
feature = item.feature
|
|
||||||
return (
|
|
||||||
h,
|
|
||||||
w,
|
|
||||||
tuple(feature.shape) if isinstance(feature, torch.Tensor) else None,
|
|
||||||
None if plan is None else tuple(sorted(plan.items())),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _mm_owner_session(self, forward_batch) -> Optional[MmOwnerSession]:
|
|
||||||
if self.mm_owner_group is None:
|
|
||||||
return None
|
|
||||||
return MmOwnerSession(
|
|
||||||
group=self.mm_owner_group,
|
|
||||||
device=self.image_start.device,
|
|
||||||
dtype=self.image_start.dtype,
|
|
||||||
width=self.config.hidden_size,
|
|
||||||
rids=list(forward_batch.rids or ()),
|
|
||||||
signature=self._image_span_signature,
|
|
||||||
engaged=has_owner_span_work(
|
|
||||||
forward_batch.mm_inputs,
|
|
||||||
forward_batch.extend_prefix_lens_cpu,
|
|
||||||
forward_batch.extend_seq_lens_cpu,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _prepare_mm_embeddings(self, input_ids, forward_batch, mm_owner):
|
|
||||||
# Keep scheduler hash IDs intact: the shared embedder clamps its input in place.
|
# Keep scheduler hash IDs intact: the shared embedder clamps its input in place.
|
||||||
input_embeds, _ = embed_mm_inputs(
|
input_embeds, _ = embed_mm_inputs(
|
||||||
mm_inputs_list=[
|
mm_inputs_list=[
|
||||||
@@ -5108,7 +5058,6 @@ class DeepseekV4ForCausalLM(nn.Module):
|
|||||||
input_ids=input_ids.clone(),
|
input_ids=input_ids.clone(),
|
||||||
input_embedding=self.get_input_embeddings(),
|
input_embedding=self.get_input_embeddings(),
|
||||||
multimodal_model=self,
|
multimodal_model=self,
|
||||||
mm_owner=mm_owner,
|
|
||||||
)
|
)
|
||||||
forward_batch.mm_input_embeds = input_embeds
|
forward_batch.mm_input_embeds = input_embeds
|
||||||
return input_embeds
|
return input_embeds
|
||||||
@@ -5116,41 +5065,6 @@ class DeepseekV4ForCausalLM(nn.Module):
|
|||||||
def get_input_embeddings(self) -> nn.Module:
|
def get_input_embeddings(self) -> nn.Module:
|
||||||
return self.model.get_input_embeddings()
|
return self.model.get_input_embeddings()
|
||||||
|
|
||||||
def prepare_model_inputs(
|
|
||||||
self,
|
|
||||||
input_ids: torch.Tensor,
|
|
||||||
forward_batch: ForwardBatch,
|
|
||||||
input_embeds: Optional[torch.Tensor],
|
|
||||||
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
|
|
||||||
if self.vision is None:
|
|
||||||
return input_ids, input_embeds
|
|
||||||
has_images = (
|
|
||||||
not forward_batch.forward_mode.is_decode()
|
|
||||||
and not forward_batch.forward_mode.is_target_verify()
|
|
||||||
and forward_batch.mm_inputs is not None
|
|
||||||
and any(x is not None for x in forward_batch.mm_inputs)
|
|
||||||
)
|
|
||||||
if has_images and input_embeds is not None:
|
|
||||||
raise ValueError("Cannot combine input_embeds and image inputs")
|
|
||||||
mm_owner = self._mm_owner_session(forward_batch) if has_images else None
|
|
||||||
# Peers may only enter the body or the CP shard once every rank has
|
|
||||||
# finished all of its fallible input preparation, the remap included.
|
|
||||||
with mm_owner.fence() if mm_owner is not None else nullcontext():
|
|
||||||
if has_images:
|
|
||||||
input_embeds = self._prepare_mm_embeddings(
|
|
||||||
input_ids, forward_batch, mm_owner
|
|
||||||
)
|
|
||||||
if not (
|
|
||||||
forward_batch.forward_mode.is_decode_or_idle()
|
|
||||||
or forward_batch.forward_mode.is_target_verify()
|
|
||||||
):
|
|
||||||
# Decode/verify IDs are already vocabulary IDs; remap prompt image
|
|
||||||
# hashes for Engram and routing.
|
|
||||||
input_ids = input_ids.masked_fill(
|
|
||||||
input_ids >= MM_PAD_SHIFT_VALUE, self.config.image_token_id
|
|
||||||
)
|
|
||||||
return input_ids, input_embeds
|
|
||||||
|
|
||||||
def set_dspark_layers_to_capture(self, layer_ids: List[int]) -> None:
|
def set_dspark_layers_to_capture(self, layer_ids: List[int]) -> None:
|
||||||
if not self.pp_group.is_last_rank:
|
if not self.pp_group.is_last_rank:
|
||||||
return
|
return
|
||||||
@@ -5201,11 +5115,31 @@ class DeepseekV4ForCausalLM(nn.Module):
|
|||||||
input_ids: torch.Tensor,
|
input_ids: torch.Tensor,
|
||||||
forward_batch: ForwardBatch,
|
forward_batch: ForwardBatch,
|
||||||
input_embeds: Optional[torch.Tensor] = None,
|
input_embeds: Optional[torch.Tensor] = None,
|
||||||
pp_proxy_tensors: Optional[PPProxyTensors] = None,
|
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
|
||||||
) -> torch.Tensor:
|
"""Prepare full-sequence image embeddings and model IDs before CP splits.
|
||||||
input_ids, input_embeds = self.prepare_model_inputs(
|
|
||||||
input_ids=input_ids, forward_batch=forward_batch, input_embeds=input_embeds
|
Scheduler hash IDs stay intact for multimodal cache keys; the language
|
||||||
)
|
model uses image_token_id for Engram masking and visual MoE routing.
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
getattr(self, "vision", None) is not None
|
||||||
|
and not forward_batch.forward_mode.is_decode()
|
||||||
|
and not forward_batch.forward_mode.is_target_verify()
|
||||||
|
and forward_batch.mm_inputs is not None
|
||||||
|
and any(x is not None for x in forward_batch.mm_inputs)
|
||||||
|
):
|
||||||
|
if input_embeds is not None:
|
||||||
|
raise ValueError("Cannot combine input_embeds and image inputs")
|
||||||
|
input_embeds = self._prepare_mm_embeddings(input_ids, forward_batch)
|
||||||
|
if getattr(self, "vision", None) is not None and not (
|
||||||
|
forward_batch.forward_mode.is_decode_or_idle()
|
||||||
|
or forward_batch.forward_mode.is_target_verify()
|
||||||
|
):
|
||||||
|
# Decode/verify IDs are already vocabulary IDs; remap prompt image
|
||||||
|
# hashes for Engram and routing.
|
||||||
|
input_ids = input_ids.masked_fill(
|
||||||
|
input_ids >= MM_PAD_SHIFT_VALUE, self.config.image_token_id
|
||||||
|
)
|
||||||
|
|
||||||
return input_ids, input_embeds
|
return input_ids, input_embeds
|
||||||
|
|
||||||
|
|||||||
@@ -222,7 +222,6 @@ class DeepseekV4ForCausalLMNextN(DeepseekV4ForCausalLM):
|
|||||||
self.quant_config = quant_config
|
self.quant_config = quant_config
|
||||||
self.wo_a_fp8 = wo_a_fp8_gemm_enabled(quant_config)
|
self.wo_a_fp8 = wo_a_fp8_gemm_enabled(quant_config)
|
||||||
self.determine_num_fused_shared_experts()
|
self.determine_num_fused_shared_experts()
|
||||||
self.vision = None
|
|
||||||
|
|
||||||
self.model = DeepseekV4ModelNextN(
|
self.model = DeepseekV4ModelNextN(
|
||||||
config, quant_config, prefix=add_prefix("model", prefix)
|
config, quant_config, prefix=add_prefix("model", prefix)
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ Covers:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from types import SimpleNamespace
|
|
||||||
from unittest.mock import AsyncMock, MagicMock
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
@@ -18,16 +17,10 @@ from sglang.srt.constants import MIS_DELIMITER_TOKEN_ID
|
|||||||
from sglang.srt.entrypoints.openai.utils import convert_embeds_to_tensors
|
from sglang.srt.entrypoints.openai.utils import convert_embeds_to_tensors
|
||||||
from sglang.srt.managers.embed_types import PositionalEmbeds
|
from sglang.srt.managers.embed_types import PositionalEmbeds
|
||||||
from sglang.srt.managers.io_struct import EmbeddingReqInput, GenerateReqInput
|
from sglang.srt.managers.io_struct import EmbeddingReqInput, GenerateReqInput
|
||||||
from sglang.srt.managers.schedule_batch import (
|
|
||||||
Modality,
|
|
||||||
MultimodalDataItem,
|
|
||||||
MultimodalInputs,
|
|
||||||
)
|
|
||||||
from sglang.srt.managers.tokenizer_manager import TokenizerManager
|
from sglang.srt.managers.tokenizer_manager import TokenizerManager
|
||||||
from sglang.srt.managers.tokenizer_manager_score_mixin import (
|
from sglang.srt.managers.tokenizer_manager_score_mixin import (
|
||||||
TokenizerManagerScoreMixin,
|
TokenizerManagerScoreMixin,
|
||||||
)
|
)
|
||||||
from sglang.srt.model_executor.model_runner import ModelRunner
|
|
||||||
from sglang.srt.runtime_context import publish, reset_context
|
from sglang.srt.runtime_context import publish, reset_context
|
||||||
from sglang.srt.server_args import ServerArgs
|
from sglang.srt.server_args import ServerArgs
|
||||||
from sglang.test.ci.ci_register import register_cpu_ci
|
from sglang.test.ci.ci_register import register_cpu_ci
|
||||||
@@ -649,87 +642,5 @@ class TestScoreRequestValidation(CustomTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestEmbedOverridesRejectMultimodal(CustomTestCase):
|
|
||||||
def setUp(self):
|
|
||||||
reset_context()
|
|
||||||
self.addCleanup(reset_context)
|
|
||||||
publish(ServerArgs(model_path="dummy"), role="tokenizer")
|
|
||||||
self.manager = TokenizerManager.__new__(TokenizerManager)
|
|
||||||
self.manager.context_len = 128
|
|
||||||
self.manager.num_reserved_tokens = 0
|
|
||||||
self.manager.allow_auto_truncate = False
|
|
||||||
self.manager.validate_total_tokens = False
|
|
||||||
self.manager.is_generation = True
|
|
||||||
|
|
||||||
def _request(self, **fields):
|
|
||||||
return GenerateReqInput(
|
|
||||||
input_ids=[10, 50, 20],
|
|
||||||
sampling_params={},
|
|
||||||
positional_embed_overrides=PositionalEmbeds(embeds=[_vec()], positions=[1]),
|
|
||||||
**fields,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_request_with_image_is_rejected(self):
|
|
||||||
req = self._request(image_data=["image.png"])
|
|
||||||
with self.assertRaisesRegex(ValueError, "overrides cannot be combined"):
|
|
||||||
self.manager._validate_one_request(req, req.input_ids)
|
|
||||||
text_only = self._request()
|
|
||||||
self.manager._validate_one_request(text_only, text_only.input_ids)
|
|
||||||
|
|
||||||
def test_unresolved_embedding_overrides_with_image_are_rejected(self):
|
|
||||||
"""EmbeddingReqInput resolves embed_overrides only after validation, so
|
|
||||||
the unresolved form must be caught at admission too."""
|
|
||||||
self.manager.is_generation = False
|
|
||||||
req = EmbeddingReqInput(
|
|
||||||
input_ids=[10, 50, 20],
|
|
||||||
sampling_params={},
|
|
||||||
embed_override_token_id=50,
|
|
||||||
embed_overrides=[_vec()],
|
|
||||||
image_data=["image.png"],
|
|
||||||
)
|
|
||||||
with self.assertRaisesRegex(ValueError, "overrides cannot be combined"):
|
|
||||||
self.manager._validate_one_request(req, req.input_ids)
|
|
||||||
req.image_data = None
|
|
||||||
self.manager._validate_one_request(req, req.input_ids)
|
|
||||||
|
|
||||||
def test_mixed_extend_batch_is_rejected_before_embedding_lookup(self):
|
|
||||||
"""Placeholder rows hold hash IDs, so the base lookup must never run
|
|
||||||
on a batch whose chunk also covers multimodal placeholders."""
|
|
||||||
embed_layer = MagicMock(
|
|
||||||
side_effect=AssertionError("embedding lookup must not run")
|
|
||||||
)
|
|
||||||
runner = SimpleNamespace(
|
|
||||||
_pp_kwargs=lambda pp_proxy_tensors: {},
|
|
||||||
model=SimpleNamespace(get_input_embeddings=lambda: embed_layer),
|
|
||||||
is_generation=True,
|
|
||||||
)
|
|
||||||
image = MultimodalDataItem(
|
|
||||||
modality=Modality.IMAGE, feature=torch.zeros(1), offsets=[(0, 1)]
|
|
||||||
)
|
|
||||||
image.set_hash(1234)
|
|
||||||
forward_batch = SimpleNamespace(
|
|
||||||
input_embeds=None,
|
|
||||||
input_ids=torch.tensor([1, 2, image.pad_value, image.pad_value]),
|
|
||||||
replace_embeds=torch.full((1, HIDDEN_DIM), 5.0),
|
|
||||||
replace_positions=torch.tensor([0]),
|
|
||||||
mm_inputs=[None, MultimodalInputs(mm_items=[image])],
|
|
||||||
extend_prefix_lens_cpu=[0, 0],
|
|
||||||
extend_seq_lens_cpu=[2, 2],
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(ValueError, "cannot share an extend batch"):
|
|
||||||
ModelRunner._extend_forward_kwargs(runner, forward_batch, None)
|
|
||||||
embed_layer.assert_not_called()
|
|
||||||
|
|
||||||
# A decoding image request in a mixed chunk has no placeholder rows here.
|
|
||||||
forward_batch.input_ids = torch.tensor([1, 2, 3])
|
|
||||||
forward_batch.extend_prefix_lens_cpu = [0, 5]
|
|
||||||
forward_batch.extend_seq_lens_cpu = [2, 1]
|
|
||||||
embed_layer.side_effect = None
|
|
||||||
embed_layer.return_value = torch.zeros(3, HIDDEN_DIM)
|
|
||||||
kwargs = ModelRunner._extend_forward_kwargs(runner, forward_batch, None)
|
|
||||||
self.assertTrue(torch.equal(kwargs["input_embeds"][0], _vec(5.0)))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -28,13 +28,7 @@ from sglang.srt.runtime_context import get_context
|
|||||||
from sglang.srt.server_args import ServerArgs, set_global_server_args_for_scheduler
|
from sglang.srt.server_args import ServerArgs, set_global_server_args_for_scheduler
|
||||||
from sglang.srt.utils.common import Range
|
from sglang.srt.utils.common import Range
|
||||||
from sglang.test.ci.ci_register import register_cpu_ci
|
from sglang.test.ci.ci_register import register_cpu_ci
|
||||||
from sglang.test.test_utils import CustomTestCase, maybe_stub_sgl_kernel
|
from sglang.test.test_utils import CustomTestCase
|
||||||
|
|
||||||
maybe_stub_sgl_kernel()
|
|
||||||
|
|
||||||
import sglang.srt.managers.scheduler as scheduler_module
|
|
||||||
from sglang.srt.disaggregation.utils import DisaggregationMode
|
|
||||||
from sglang.srt.managers.scheduler import Scheduler
|
|
||||||
|
|
||||||
register_cpu_ci(est_time=11, suite="base-a-test-cpu")
|
register_cpu_ci(est_time=11, suite="base-a-test-cpu")
|
||||||
|
|
||||||
@@ -302,139 +296,6 @@ class TestPrefillAdder(CustomTestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(adder.can_run_list, [first])
|
self.assertEqual(adder.can_run_list, [first])
|
||||||
|
|
||||||
def test_embed_override_and_multimodal_requests_never_share_a_batch(self):
|
|
||||||
def tagged(rid, *, multimodal=False, overrides=False):
|
|
||||||
req = self.create_shared_req(rid)
|
|
||||||
req.multimodal_inputs = object() if multimodal else None
|
|
||||||
req.positional_embed_overrides = object() if overrides else None
|
|
||||||
return req
|
|
||||||
|
|
||||||
for first, second in (
|
|
||||||
(tagged("image", multimodal=True), tagged("override", overrides=True)),
|
|
||||||
(tagged("override", overrides=True), tagged("image", multimodal=True)),
|
|
||||||
):
|
|
||||||
with self.subTest(first=first.rid):
|
|
||||||
adder = self.create_shared_adder()
|
|
||||||
self.assertTrue(adder.can_share_extend_batch(first))
|
|
||||||
adder.add_one_req(
|
|
||||||
first, has_chunked_req=False, truncation_align_size=None
|
|
||||||
)
|
|
||||||
self.assertEqual(adder.can_run_list, [first])
|
|
||||||
self.assertFalse(adder.can_share_extend_batch(second))
|
|
||||||
self.assertTrue(adder.can_share_extend_batch(tagged("text")))
|
|
||||||
|
|
||||||
adder = self.create_shared_adder()
|
|
||||||
chunked = tagged("chunked-image", multimodal=True)
|
|
||||||
chunked.full_untruncated_fill_ids = list(range(64))
|
|
||||||
self.assertIs(adder.add_chunked_req(chunked), chunked)
|
|
||||||
self.assertFalse(
|
|
||||||
adder.can_share_extend_batch(tagged("override", overrides=True))
|
|
||||||
)
|
|
||||||
|
|
||||||
def create_admission_scheduler(self, *, chunked_req) -> Scheduler:
|
|
||||||
allocator = self.create_token_allocator(available_size=4096)
|
|
||||||
allocator.page_size = 1
|
|
||||||
self.mock_tree_cache.supports_mamba.return_value = False
|
|
||||||
self.mock_tree_cache.is_tree_cache.return_value = False
|
|
||||||
self.mock_tree_cache.supports_fast_match_prefix.return_value = False
|
|
||||||
self.mock_tree_cache.storage_prefetch_retries = None
|
|
||||||
scheduler = Scheduler.__new__(Scheduler)
|
|
||||||
scheduler.grammar_manager = SimpleNamespace(has_waiting_grammars=lambda: False)
|
|
||||||
scheduler.enable_priority_preemption = False
|
|
||||||
scheduler.enable_priority_scheduling = False
|
|
||||||
scheduler.is_hybrid_swa = False
|
|
||||||
scheduler.min_free_slots_delayer = None
|
|
||||||
scheduler.get_num_allocatable_reqs = lambda *args, **kwargs: 64
|
|
||||||
scheduler.policy = SchedulePolicy(
|
|
||||||
policy="fcfs",
|
|
||||||
tree_cache=self.mock_tree_cache,
|
|
||||||
enable_hierarchical_cache=False,
|
|
||||||
enable_priority_scheduling=False,
|
|
||||||
schedule_low_priority_values_first=False,
|
|
||||||
)
|
|
||||||
scheduler.processed_tokens_counter = 0
|
|
||||||
scheduler.chunked_prefill_size = 16
|
|
||||||
scheduler.dynamic_chunk_sizer = None
|
|
||||||
scheduler.tp_worker = SimpleNamespace(
|
|
||||||
model_runner=SimpleNamespace(attn_backend=object(), prefill_aware_swa=False)
|
|
||||||
)
|
|
||||||
scheduler.page_size = 1
|
|
||||||
scheduler.tree_cache = self.mock_tree_cache
|
|
||||||
scheduler.token_to_kv_pool_allocator = allocator
|
|
||||||
scheduler.new_token_ratio_tracker = SimpleNamespace(current=1.0)
|
|
||||||
scheduler.max_prefill_tokens = 16384
|
|
||||||
scheduler.is_mixed_chunk = False
|
|
||||||
scheduler.priority_scheduling_preemption_threshold = 0
|
|
||||||
scheduler.max_prefill_bs = 64
|
|
||||||
scheduler.max_running_requests = 64
|
|
||||||
scheduler.dllm_config = None
|
|
||||||
scheduler.enable_lora = False
|
|
||||||
scheduler.req_to_token_pool = SimpleNamespace()
|
|
||||||
scheduler.disaggregation_mode = DisaggregationMode.NULL
|
|
||||||
scheduler.enable_hicache_storage = False
|
|
||||||
scheduler.enable_hierarchical_cache = False
|
|
||||||
scheduler.enable_unified_cache_external_linker = False
|
|
||||||
scheduler.truncation_align_size = None
|
|
||||||
scheduler.model_config = None
|
|
||||||
scheduler.enable_overlap = False
|
|
||||||
scheduler.spec_algorithm = None
|
|
||||||
scheduler.load_inquirer = MagicMock()
|
|
||||||
scheduler.chunked_req = chunked_req
|
|
||||||
scheduler.waiting_queue = []
|
|
||||||
return scheduler
|
|
||||||
|
|
||||||
def run_admission_pass(self, scheduler: Scheduler) -> list:
|
|
||||||
running_batch = self.create_running_batch()
|
|
||||||
running_batch.batch_is_full = False
|
|
||||||
with (
|
|
||||||
patch.object(scheduler_module, "ScheduleBatch") as schedule_batch,
|
|
||||||
patch.object(scheduler_module, "PrefillStats"),
|
|
||||||
patch.object(scheduler_module, "set_time_batch"),
|
|
||||||
):
|
|
||||||
new_batch, _ = scheduler._get_new_batch_prefill_raw(None, running_batch)
|
|
||||||
if new_batch is None:
|
|
||||||
return []
|
|
||||||
admitted = list(schedule_batch.init_new.call_args.args[0])
|
|
||||||
for req in admitted:
|
|
||||||
req.prefix_indices = list(range(req.extend_range.end))
|
|
||||||
return admitted
|
|
||||||
|
|
||||||
def test_fcfs_admits_override_request_once_image_continuation_drains(self):
|
|
||||||
"""An override request at the queue head must be admitted once the image
|
|
||||||
chunk ahead of it drains, even while more image requests keep arriving."""
|
|
||||||
|
|
||||||
def tagged(rid, length, *, multimodal=False, overrides=False):
|
|
||||||
req = self.create_shared_req(rid)
|
|
||||||
req.origin_input_ids = list(range(length))
|
|
||||||
req.full_untruncated_fill_ids = list(range(length))
|
|
||||||
req.multimodal_inputs = object() if multimodal else None
|
|
||||||
req.positional_embed_overrides = object() if overrides else None
|
|
||||||
req.beam_group = None
|
|
||||||
req.inflight_middle_chunks = 0
|
|
||||||
return req
|
|
||||||
|
|
||||||
continuation = tagged("image-continuation", 20, multimodal=True)
|
|
||||||
continuation.prefix_indices = list(range(16))
|
|
||||||
scheduler = self.create_admission_scheduler(chunked_req=continuation)
|
|
||||||
override = tagged("override", 4, overrides=True)
|
|
||||||
scheduler.waiting_queue = [override]
|
|
||||||
|
|
||||||
admitted_at = None
|
|
||||||
for pass_index in range(6):
|
|
||||||
scheduler.waiting_queue.append(
|
|
||||||
tagged(f"image-{pass_index}", 16, multimodal=True)
|
|
||||||
)
|
|
||||||
admitted = self.run_admission_pass(scheduler)
|
|
||||||
self.assertFalse(
|
|
||||||
any(r.multimodal_inputs is not None for r in admitted)
|
|
||||||
and any(r.positional_embed_overrides is not None for r in admitted)
|
|
||||||
)
|
|
||||||
if any(r is override for r in admitted):
|
|
||||||
admitted_at = pass_index
|
|
||||||
break
|
|
||||||
self.assertIsNotNone(admitted_at)
|
|
||||||
self.assertNotIn(override, scheduler.waiting_queue)
|
|
||||||
|
|
||||||
def test_shared_admission_rechecks_after_prefix_lock(self):
|
def test_shared_admission_rechecks_after_prefix_lock(self):
|
||||||
adder = self.create_shared_adder()
|
adder = self.create_shared_adder()
|
||||||
self.assertIsNotNone(adder.token_to_kv_pool_allocator.alloc(24))
|
self.assertIsNotNone(adder.token_to_kv_pool_allocator.alloc(24))
|
||||||
|
|||||||
@@ -1,261 +0,0 @@
|
|||||||
"""Vision inputs under prefill CP merge on the full extend layout before the shard."""
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
from contextlib import contextmanager
|
|
||||||
from types import SimpleNamespace
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import torch
|
|
||||||
from torch import nn
|
|
||||||
|
|
||||||
from sglang.srt.layers.cp.base import init_cp_strategy
|
|
||||||
from sglang.srt.layers.cp.utils import prepare_cp_forward
|
|
||||||
from sglang.srt.managers import mm_schedule
|
|
||||||
from sglang.srt.managers.schedule_batch import (
|
|
||||||
Modality,
|
|
||||||
MultimodalDataItem,
|
|
||||||
MultimodalInputs,
|
|
||||||
)
|
|
||||||
from sglang.srt.model_executor.forward_batch_info import ForwardMode
|
|
||||||
from sglang.srt.model_executor.runner.eager_runner import EagerRunner
|
|
||||||
from sglang.srt.models.deepseek_v4 import DeepseekV4ForCausalLM
|
|
||||||
from sglang.srt.runtime_context import get_parallel
|
|
||||||
from sglang.test.ci.ci_register import register_cpu_ci
|
|
||||||
from sglang.test.test_utils import CustomTestCase
|
|
||||||
|
|
||||||
register_cpu_ci(est_time=15, suite="base-a-test-cpu")
|
|
||||||
|
|
||||||
HIDDEN = 8
|
|
||||||
VOCAB = 64
|
|
||||||
IMAGE_TOKEN_ID = 7
|
|
||||||
CP_SIZE = 4
|
|
||||||
# (prefix_len, extend_len) per request. Request 1 carries one image whose span
|
|
||||||
# [2, 8] starts inside its prefix, so only span rows 1..6 land in this chunk.
|
|
||||||
CHUNKS = [(0, 7), (3, 9), (1, 5)]
|
|
||||||
IMAGE_OFFSET = (2, 8)
|
|
||||||
IMAGE_HASH = 12345
|
|
||||||
NUM_TOKENS = sum(extend_len for _, extend_len in CHUNKS)
|
|
||||||
# 21 tokens over 4 ranks give logical [6, 5, 5, 5], padded to the CP alignment.
|
|
||||||
PHYSICAL_ROWS = 8
|
|
||||||
IMAGE_ROWS = torch.arange(7, 13)
|
|
||||||
POSITIONS = torch.cat([torch.arange(p, p + n) for p, n in CHUNKS])
|
|
||||||
|
|
||||||
|
|
||||||
def _image_span(item: MultimodalDataItem) -> torch.Tensor:
|
|
||||||
start, end = item.offsets[0]
|
|
||||||
rows = end - start + 1
|
|
||||||
return torch.arange(rows * HIDDEN, dtype=torch.float32).view(rows, HIDDEN) + 100.0
|
|
||||||
|
|
||||||
|
|
||||||
def _pad(x: torch.Tensor) -> torch.Tensor:
|
|
||||||
return torch.cat([x, x.new_zeros(PHYSICAL_ROWS - x.shape[0], *x.shape[1:])])
|
|
||||||
|
|
||||||
|
|
||||||
class _RecordingBody:
|
|
||||||
def __init__(self, embed: nn.Embedding):
|
|
||||||
self.embed = embed
|
|
||||||
self.calls = []
|
|
||||||
|
|
||||||
def get_input_embeddings(self):
|
|
||||||
return self.embed
|
|
||||||
|
|
||||||
def __call__(self, input_ids, positions, forward_batch, input_embeds=None):
|
|
||||||
self.calls.append(
|
|
||||||
SimpleNamespace(
|
|
||||||
input_ids=input_ids,
|
|
||||||
positions=positions,
|
|
||||||
input_embeds=input_embeds,
|
|
||||||
input_ids_global=forward_batch.input_ids_global,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return input_embeds, input_embeds
|
|
||||||
|
|
||||||
|
|
||||||
class _VisionStub(DeepseekV4ForCausalLM):
|
|
||||||
def __init__(self, embed: nn.Embedding):
|
|
||||||
nn.Module.__init__(self)
|
|
||||||
self.config = SimpleNamespace(image_token_id=IMAGE_TOKEN_ID)
|
|
||||||
self.vision = object()
|
|
||||||
self.tp_size = 1
|
|
||||||
self.mm_owner_group = None
|
|
||||||
self.model = _RecordingBody(embed)
|
|
||||||
self.pp_group = SimpleNamespace(is_last_rank=True)
|
|
||||||
self.lm_head = object()
|
|
||||||
self.capture_aux_hidden_states = False
|
|
||||||
self.logits_calls = []
|
|
||||||
|
|
||||||
def get_image_feature(self, items):
|
|
||||||
return [_image_span(item) for item in items]
|
|
||||||
|
|
||||||
def logits_processor(
|
|
||||||
self,
|
|
||||||
input_ids,
|
|
||||||
hidden_states,
|
|
||||||
lm_head,
|
|
||||||
logits_metadata,
|
|
||||||
aux_hidden_states=None,
|
|
||||||
hidden_states_before_norm=None,
|
|
||||||
):
|
|
||||||
self.logits_calls.append(
|
|
||||||
SimpleNamespace(
|
|
||||||
input_ids=input_ids,
|
|
||||||
hidden_states=hidden_states,
|
|
||||||
logits_metadata=logits_metadata,
|
|
||||||
hidden_states_before_norm=hidden_states_before_norm,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return object()
|
|
||||||
|
|
||||||
|
|
||||||
def _build_batch():
|
|
||||||
item = MultimodalDataItem(
|
|
||||||
modality=Modality.IMAGE, feature=torch.zeros(1), offsets=[IMAGE_OFFSET]
|
|
||||||
)
|
|
||||||
item.set_hash(IMAGE_HASH)
|
|
||||||
ids = list(range(10, 17))
|
|
||||||
ids += [item.pad_value] * len(IMAGE_ROWS) + [20, 21, 22]
|
|
||||||
ids += list(range(30, 35))
|
|
||||||
forward_batch = SimpleNamespace(
|
|
||||||
forward_mode=ForwardMode.EXTEND,
|
|
||||||
mm_inputs=[
|
|
||||||
MultimodalInputs(mm_items=[]),
|
|
||||||
MultimodalInputs(mm_items=[item], im_token_id=IMAGE_TOKEN_ID),
|
|
||||||
None,
|
|
||||||
],
|
|
||||||
extend_prefix_lens_cpu=[prefix for prefix, _ in CHUNKS],
|
|
||||||
extend_seq_lens_cpu=[extend_len for _, extend_len in CHUNKS],
|
|
||||||
seq_lens_cpu=[prefix + extend_len for prefix, extend_len in CHUNKS],
|
|
||||||
input_ids=torch.tensor(ids, dtype=torch.long),
|
|
||||||
positions=POSITIONS.clone(),
|
|
||||||
mm_input_embeds=None,
|
|
||||||
attn_cp_metadata=None,
|
|
||||||
global_num_tokens_cpu=None,
|
|
||||||
out_cache_loc=None,
|
|
||||||
input_ids_global=torch.zeros(1, dtype=torch.long),
|
|
||||||
)
|
|
||||||
return forward_batch, item
|
|
||||||
|
|
||||||
|
|
||||||
def _expected_embeds(embed, scheduler_ids, item):
|
|
||||||
with torch.no_grad():
|
|
||||||
full = embed(scheduler_ids.clamp(max=VOCAB - 1))
|
|
||||||
full[IMAGE_ROWS] = _image_span(item)[1:7]
|
|
||||||
return full
|
|
||||||
|
|
||||||
|
|
||||||
def _canonical(scheduler_ids):
|
|
||||||
canonical = scheduler_ids.clone()
|
|
||||||
canonical[IMAGE_ROWS] = IMAGE_TOKEN_ID
|
|
||||||
return canonical
|
|
||||||
|
|
||||||
|
|
||||||
class TestDeepseekV41VisionPrefillCPInputs(CustomTestCase):
|
|
||||||
def setUp(self):
|
|
||||||
mm_schedule.init_mm_embedding_cache(1 << 20)
|
|
||||||
init_cp_strategy(
|
|
||||||
enable_prefill_cp=True, cp_size=CP_SIZE, cp_strategy="interleave"
|
|
||||||
)
|
|
||||||
torch.manual_seed(0)
|
|
||||||
self.embed = nn.Embedding(VOCAB, HIDDEN)
|
|
||||||
self.model = _VisionStub(self.embed)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
init_cp_strategy(enable_prefill_cp=False, cp_size=1, cp_strategy="interleave")
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def _cp_collectives(self, full: torch.Tensor, rank: int):
|
|
||||||
def all_gather(output, input_tensor):
|
|
||||||
# Peers contribute their expected shards; this rank's rows come from
|
|
||||||
# what the runner actually handed to the collective.
|
|
||||||
output.zero_()
|
|
||||||
for peer in range(CP_SIZE):
|
|
||||||
rows = full[peer::CP_SIZE]
|
|
||||||
output[peer * PHYSICAL_ROWS : peer * PHYSICAL_ROWS + rows.shape[0]] = (
|
|
||||||
rows
|
|
||||||
)
|
|
||||||
output[rank * PHYSICAL_ROWS : (rank + 1) * PHYSICAL_ROWS] = input_tensor
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch("torch.cuda.current_stream", return_value=None),
|
|
||||||
patch(
|
|
||||||
"sglang.srt.layers.cp.interleave.attn_cp_all_gather_into_tensor",
|
|
||||||
side_effect=all_gather,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"sglang.srt.layers.cp.interleave.is_allocation_symmetric",
|
|
||||||
return_value=False,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"sglang.srt.layers.cp.interleave.use_symmetric_memory",
|
|
||||||
return_value=torch.no_grad(),
|
|
||||||
),
|
|
||||||
):
|
|
||||||
yield
|
|
||||||
|
|
||||||
def _prepare(self, forward_batch, input_embeds=None):
|
|
||||||
with torch.no_grad():
|
|
||||||
return self.model.prepare_model_inputs(
|
|
||||||
input_ids=forward_batch.input_ids,
|
|
||||||
forward_batch=forward_batch,
|
|
||||||
input_embeds=input_embeds,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_cp_runner_merges_before_shard(self):
|
|
||||||
runner = EagerRunner.__new__(EagerRunner)
|
|
||||||
runner.model_runner = SimpleNamespace(model=self.model)
|
|
||||||
padded = torch.zeros(CP_SIZE * PHYSICAL_ROWS, dtype=torch.long)
|
|
||||||
|
|
||||||
for rank in range(CP_SIZE):
|
|
||||||
forward_batch, item = _build_batch()
|
|
||||||
routing_sentinel = forward_batch.input_ids_global
|
|
||||||
scheduler_ids = forward_batch.input_ids.clone()
|
|
||||||
canonical = _canonical(scheduler_ids)
|
|
||||||
full = _expected_embeds(self.embed, scheduler_ids, item)
|
|
||||||
padded[:NUM_TOKENS] = canonical
|
|
||||||
rank_major_ids = padded.view(-1, CP_SIZE).T.flatten()
|
|
||||||
self.model.model.calls.clear()
|
|
||||||
self.model.logits_calls.clear()
|
|
||||||
|
|
||||||
with (
|
|
||||||
get_parallel().override(
|
|
||||||
attn_cp_rank=rank, attn_cp_size=CP_SIZE, attn_cp_group=object()
|
|
||||||
),
|
|
||||||
self._cp_collectives(full, rank),
|
|
||||||
torch.no_grad(),
|
|
||||||
):
|
|
||||||
prepare_cp_forward(forward_batch)
|
|
||||||
runner._execute_extend_cp(forward_batch, {})
|
|
||||||
|
|
||||||
with self.subTest(rank=rank):
|
|
||||||
metadata = forward_batch.attn_cp_metadata
|
|
||||||
self.assertEqual(metadata.per_rank_actual_token, [PHYSICAL_ROWS] * 4)
|
|
||||||
(body,) = self.model.model.calls
|
|
||||||
self.assertTrue(
|
|
||||||
torch.equal(body.input_ids, _pad(canonical[rank::CP_SIZE]))
|
|
||||||
)
|
|
||||||
self.assertTrue(
|
|
||||||
torch.equal(body.positions, _pad(POSITIONS[rank::CP_SIZE]))
|
|
||||||
)
|
|
||||||
self.assertTrue(
|
|
||||||
torch.equal(body.input_embeds, _pad(full[rank::CP_SIZE]))
|
|
||||||
)
|
|
||||||
self.assertTrue(torch.equal(body.input_ids_global, rank_major_ids))
|
|
||||||
|
|
||||||
(logits,) = self.model.logits_calls
|
|
||||||
self.assertTrue(torch.equal(logits.input_ids, canonical))
|
|
||||||
self.assertTrue(torch.equal(logits.hidden_states, full))
|
|
||||||
self.assertTrue(torch.equal(logits.hidden_states_before_norm, full))
|
|
||||||
self.assertIs(logits.logits_metadata, forward_batch)
|
|
||||||
|
|
||||||
self.assertTrue(torch.equal(forward_batch.mm_input_embeds, full))
|
|
||||||
self.assertTrue(torch.equal(forward_batch.input_ids, scheduler_ids))
|
|
||||||
self.assertIs(forward_batch.input_ids_global, routing_sentinel)
|
|
||||||
|
|
||||||
def test_external_embeddings_with_images_are_rejected(self):
|
|
||||||
forward_batch, _ = _build_batch()
|
|
||||||
with self.assertRaisesRegex(ValueError, "Cannot combine"):
|
|
||||||
self._prepare(forward_batch, input_embeds=torch.zeros(NUM_TOKENS, HIDDEN))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
@@ -29,7 +29,6 @@ from sglang.srt.arg_groups.cuda_graph_hook import (
|
|||||||
finalize_cuda_graph_prefill_max_context,
|
finalize_cuda_graph_prefill_max_context,
|
||||||
handle_cuda_graph_config,
|
handle_cuda_graph_config,
|
||||||
)
|
)
|
||||||
from sglang.srt.arg_groups.deepseek_v4_hook import validate_deepseek_v41_features
|
|
||||||
from sglang.srt.arg_groups.hicache_hook import (
|
from sglang.srt.arg_groups.hicache_hook import (
|
||||||
handle_hicache,
|
handle_hicache,
|
||||||
handle_hicache_ratio_default,
|
handle_hicache_ratio_default,
|
||||||
@@ -46,7 +45,6 @@ from sglang.srt.arg_groups.kv_cache_hook import (
|
|||||||
)
|
)
|
||||||
from sglang.srt.arg_groups.mamba_hook import handle_mamba_backend
|
from sglang.srt.arg_groups.mamba_hook import handle_mamba_backend
|
||||||
from sglang.srt.arg_groups.memory_hook import handle_gpu_memory_settings
|
from sglang.srt.arg_groups.memory_hook import handle_gpu_memory_settings
|
||||||
from sglang.srt.arg_groups.model_hook import handle_model_specific_adjustments
|
|
||||||
from sglang.srt.arg_groups.model_path_hook import handle_load_format
|
from sglang.srt.arg_groups.model_path_hook import handle_load_format
|
||||||
from sglang.srt.arg_groups.moe_hook import (
|
from sglang.srt.arg_groups.moe_hook import (
|
||||||
handle_a2a_moe,
|
handle_a2a_moe,
|
||||||
@@ -4071,86 +4069,5 @@ class TestLazyReexports(CustomTestCase):
|
|||||||
server_args_module.NotAThing
|
server_args_module.NotAThing
|
||||||
|
|
||||||
|
|
||||||
class TestDeepseekV41VisionPrefillCPArgs(CustomTestCase):
|
|
||||||
def _args(
|
|
||||||
self,
|
|
||||||
*,
|
|
||||||
vision_n_layers=2,
|
|
||||||
prefill_backend=Backend.DISABLED,
|
|
||||||
lock_prefill_backend=False,
|
|
||||||
**overrides,
|
|
||||||
):
|
|
||||||
fields = dict(
|
|
||||||
model_path="dummy",
|
|
||||||
enable_prefill_cp=True,
|
|
||||||
cp_strategy="interleave",
|
|
||||||
tp_size=2,
|
|
||||||
)
|
|
||||||
fields.update(overrides)
|
|
||||||
server_args = ServerArgs(**fields)
|
|
||||||
server_args._model_config = SimpleNamespace(
|
|
||||||
hf_config=SimpleNamespace(
|
|
||||||
architectures=["DeepseekV4ForCausalLM"],
|
|
||||||
model_type="deepseek_v41",
|
|
||||||
vision_n_layers=vision_n_layers,
|
|
||||||
),
|
|
||||||
nvfp4_moe_meta=None,
|
|
||||||
is_fp4_experts=False,
|
|
||||||
)
|
|
||||||
# The dummy path does not initialize phase configs.
|
|
||||||
server_args.cuda_graph_config = CudaGraphConfig(
|
|
||||||
decode=PhaseConfig(backend=Backend.FULL, max_bs=512),
|
|
||||||
prefill=PhaseConfig(backend=prefill_backend, max_bs=512),
|
|
||||||
)
|
|
||||||
server_args._resolved_overrides = []
|
|
||||||
server_args._cuda_graph_config_locked = (
|
|
||||||
{(Phase.PREFILL, "backend")} if lock_prefill_backend else set()
|
|
||||||
)
|
|
||||||
return server_args
|
|
||||||
|
|
||||||
@override_platform(is_cuda=True, is_hip=False)
|
|
||||||
def test_encoder_swa_replay_is_rejected_in_model_hook_order(self):
|
|
||||||
"""The V4.1 validator runs before the CP validator declares attn_cp_size,
|
|
||||||
so encoder SWA replay used to pass resolution with vision prefill CP."""
|
|
||||||
args = self._args(
|
|
||||||
enable_encoder_swa_bounded_replay=True,
|
|
||||||
max_running_requests=4,
|
|
||||||
chunked_prefill_size=128,
|
|
||||||
)
|
|
||||||
with self.assertRaisesRegex(
|
|
||||||
ValueError,
|
|
||||||
"encoder-swa-bounded-replay does not support context parallelism",
|
|
||||||
):
|
|
||||||
handle_model_specific_adjustments(args)
|
|
||||||
|
|
||||||
def test_zigzag_is_rejected_only_with_vision(self):
|
|
||||||
with self.assertRaisesRegex(ValueError, "requires --cp-strategy interleave"):
|
|
||||||
validate_deepseek_v41_features(self._args(cp_strategy="zigzag"))
|
|
||||||
validate_deepseek_v41_features(
|
|
||||||
self._args(cp_strategy="zigzag", vision_n_layers=0)
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_prefill_graph_explicit_rejects_and_default_resolves_eager(self):
|
|
||||||
with self.assertRaisesRegex(ValueError, "runs eager prefill"):
|
|
||||||
validate_deepseek_v41_features(
|
|
||||||
self._args(prefill_backend=Backend.BREAKABLE, lock_prefill_backend=True)
|
|
||||||
)
|
|
||||||
args = self._args(prefill_backend=Backend.BREAKABLE)
|
|
||||||
validate_deepseek_v41_features(args)
|
|
||||||
self.assertEqual(
|
|
||||||
resolution_result(args, "cuda_graph_config").prefill.backend,
|
|
||||||
Backend.DISABLED,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_dspark_with_decoder_swa_bounded_replay_is_rejected(self):
|
|
||||||
with self.assertRaisesRegex(ValueError, "DSpark.*decoder-swa-bounded-replay"):
|
|
||||||
validate_deepseek_v41_features(
|
|
||||||
self._args(
|
|
||||||
speculative_algorithm="DSPARK",
|
|
||||||
enable_decoder_swa_bounded_replay=True,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user