feat(pd): PD 长上下文 adaptive concurrency bench(SLO 方案 A,并发 +16)
- matrix.json: 3 个 shape(64k/128, 16k/1k, 1k/4k) - run_adaptive_concurrency_pd.sh: PD 专用 adaptive 脚本 - 复用 adaptive_bench_lib.sh(并发搜索/SLO 停止/OOM 检测/完整产物) - server 生命周期函数 no-op(PD 服务常驻,不启停) - 加 --flush-cache(配合 --disable-radix-cache 测纯净 TTFT/TPOT) - 离线环境变量 + 本地 tokenizer(避免 HF 在线下载) - adaptive_config.env: SEARCH_ADDEND=16 +16 递增,上限 64,回退 8/1 - config.env: 新增 get_ttft_slo_ms 分层 SLO(1k->4s, 16k->15s, 64k->30s)
This commit is contained in:
parent
fe375e1307
commit
c69831f258
@ -0,0 +1,49 @@
|
|||||||
|
# PD 分离(MoonCake RDMA)长上下文 adaptive concurrency 配置。
|
||||||
|
#
|
||||||
|
# 并发搜索:从 C=16 起 +16 递增(SEARCH_ADDEND=16),上限 64。
|
||||||
|
# SEARCH_MULTIPLIER 为占位(库日志无条件引用它),实际走 SEARCH_ADDEND 加法递增。
|
||||||
|
# 若初始并发就违反 TTFT SLO,回退 C=8 → C=1(SEARCH_INITIAL_BACKOFF)。
|
||||||
|
# 若 C=1 仍严重超 SLO 或 OOM,停止该 shape。
|
||||||
|
# SLO 方案 A:TTFT P95 随 ISL 分层递增(见 config.env 的 get_ttft_slo_ms)。
|
||||||
|
|
||||||
|
SEARCH_MULTIPLIER="${SEARCH_MULTIPLIER:-2}"
|
||||||
|
SEARCH_START_CONCURRENCY="${SEARCH_START_CONCURRENCY:-16}"
|
||||||
|
SEARCH_ADDEND=16
|
||||||
|
SEARCH_MAX_CONCURRENCY="${SEARCH_MAX_CONCURRENCY:-64}"
|
||||||
|
# add16 初始探测违反 SLO 时回退:16 -> 8 -> 1。
|
||||||
|
SEARCH_INITIAL_BACKOFF_CONCURRENCIES="8 1"
|
||||||
|
|
||||||
|
# 长上下文场景不用整组跳过(64k 单并发 TTFT 可能就较高)。
|
||||||
|
# TTFT_GROUP_SKIP_MS 留空禁用。
|
||||||
|
|
||||||
|
# TTFT_SLO_MS 是 flat fallback;config.env 定义了 get_ttft_slo_ms() 时以函数为准。
|
||||||
|
TTFT_SLO_MS="${TTFT_SLO_MS:-4000}"
|
||||||
|
ENABLE_TTFT_SLO_STOP="${ENABLE_TTFT_SLO_STOP:-1}"
|
||||||
|
|
||||||
|
# 吞吐饱和判定(沿用仓库默认)。
|
||||||
|
TPS_MIN_GAIN_PCT="${TPS_MIN_GAIN_PCT:-2.0}"
|
||||||
|
PLATEAU_PATIENCE="${PLATEAU_PATIENCE:-2}"
|
||||||
|
|
||||||
|
# Warmup 请求数上限(0=不限,按并发自适应)。长上下文大并发 warmup 昂贵,可设小上限。
|
||||||
|
BENCH_WARMUP_MAX_REQUESTS="${BENCH_WARMUP_MAX_REQUESTS:-0}"
|
||||||
|
|
||||||
|
# 每并发点的请求数 = concurrency * NUM_PROMPTS_MULTIPLIER。
|
||||||
|
NUM_PROMPTS_MULTIPLIER="${NUM_PROMPTS_MULTIPLIER:-5}"
|
||||||
|
|
||||||
|
# random 数据(ShareGPT 抽样)或 random-ids(整数 token)。长上下文建议 random-ids
|
||||||
|
# 避免 ShareGPT 前缀干扰测量;BENCH_DATASET_NAME 见 config.env。
|
||||||
|
RANDOM_RANGE_RATIO="${RANDOM_RANGE_RATIO:-1.0}"
|
||||||
|
|
||||||
|
# 长度容差与重试。
|
||||||
|
INPUT_LENGTH_TOLERANCE_PCT="${INPUT_LENGTH_TOLERANCE_PCT:-5.0}"
|
||||||
|
OUTPUT_LENGTH_TOLERANCE_PCT="${OUTPUT_LENGTH_TOLERANCE_PCT:-10.0}"
|
||||||
|
MAX_POINT_RETRIES="${MAX_POINT_RETRIES:-1}"
|
||||||
|
SCENARIO_TIMEOUT_S="${SCENARIO_TIMEOUT_S:-3600}"
|
||||||
|
GPU_MEM_SAMPLE_INTERVAL_S="${GPU_MEM_SAMPLE_INTERVAL_S:-1}"
|
||||||
|
|
||||||
|
# 过滤与限制(smoke 用)。
|
||||||
|
TP_LIST="${TP_LIST:-}"
|
||||||
|
ISL_LIST="${ISL_LIST:-}"
|
||||||
|
OSL_LIST="${OSL_LIST:-}"
|
||||||
|
GRID_LIMIT="${GRID_LIMIT:-0}"
|
||||||
|
DRY_RUN="${DRY_RUN:-0}"
|
||||||
@ -30,5 +30,30 @@ DOCKER_CLIENT_IMAGE="${DOCKER_CLIENT_IMAGE:-lmsysorg/sglang:kimi-k3}"
|
|||||||
P_DEPLOY_PROFILE="${P_DEPLOY_PROFILE:-pro6000/kimi3_pro6000_pd_prefill}"
|
P_DEPLOY_PROFILE="${P_DEPLOY_PROFILE:-pro6000/kimi3_pro6000_pd_prefill}"
|
||||||
D_DEPLOY_PROFILE="${D_DEPLOY_PROFILE:-pro6000/kimi3_pro6000_pd_decode}"
|
D_DEPLOY_PROFILE="${D_DEPLOY_PROFILE:-pro6000/kimi3_pro6000_pd_decode}"
|
||||||
|
|
||||||
|
# ---- Bench client 配置(供 run_adaptive_concurrency_pd.sh 使用)----
|
||||||
|
# 长上下文用 random-ids(整数 token),避免 ShareGPT 前缀干扰测量。
|
||||||
|
BENCH_DATASET_NAME="${BENCH_DATASET_NAME:-random-ids}"
|
||||||
|
DATASET_PATH="${DATASET_PATH:-}"
|
||||||
|
SGLANG_BENCH_MODULE="${SGLANG_BENCH_MODULE:-sglang.bench_serving}"
|
||||||
|
GPU_MEM_SAMPLE_INTERVAL_S="${GPU_MEM_SAMPLE_INTERVAL_S:-1}"
|
||||||
|
|
||||||
# Per-scenario timeout to avoid hangs (seconds).
|
# Per-scenario timeout to avoid hangs (seconds).
|
||||||
SCENARIO_TIMEOUT_S="${SCENARIO_TIMEOUT_S:-3600}"
|
SCENARIO_TIMEOUT_S="${SCENARIO_TIMEOUT_S:-3600}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Tiered TTFT SLO by input sequence length (方案 A).
|
||||||
|
# 长上下文场景 SLO 随 ISL 递增:prefill 有固有计算成本,TTFT 必须随输入放宽。
|
||||||
|
# Kimi-K3 混合线性注意力在 RTX 6000D 上 prefill 较慢,阈值比 glm52 略宽。
|
||||||
|
# 对应三个 shape: 1k->4s, 16k->15s, 64k->30s。
|
||||||
|
# 由 adaptive_bench_lib.sh 的并发扫描调用:ttft_p95 超阈值即停止该 shape。
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
get_ttft_slo_ms() {
|
||||||
|
local isl="$1"
|
||||||
|
if (( isl <= 2048 )); then echo 4000
|
||||||
|
elif (( isl <= 8192 )); then echo 8000
|
||||||
|
elif (( isl <= 32768 )); then echo 15000
|
||||||
|
elif (( isl <= 131072 )); then echo 30000
|
||||||
|
else echo 50000
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
TTFT_SLO_TIERS_DESC="≤2k:4s, ≤8k:8s, ≤32k:15s, ≤128k:30s, >128k:50s"
|
||||||
|
|||||||
9
experiments/pro6000/kimi3_pro6000_pd_rdma/matrix.json
Normal file
9
experiments/pro6000/kimi3_pro6000_pd_rdma/matrix.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"comment": "PD 分离(MoonCake RDMA)长上下文 bench:并发 +16 递增搜索直到 TTFT SLO 或 OOM。ISL=64k/16k/1k。",
|
||||||
|
"mode": "Y",
|
||||||
|
"matrix": {
|
||||||
|
"65536": { "128": "Y" },
|
||||||
|
"16384": { "1024": "Y" },
|
||||||
|
"1024": { "4096": "Y" }
|
||||||
|
}
|
||||||
|
}
|
||||||
133
experiments/pro6000/kimi3_pro6000_pd_rdma/run_adaptive_concurrency_pd.sh
Executable file
133
experiments/pro6000/kimi3_pro6000_pd_rdma/run_adaptive_concurrency_pd.sh
Executable file
@ -0,0 +1,133 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# PD 分离(MoonCake RDMA)长上下文 adaptive concurrency 搜索。
|
||||||
|
# 并发 +16 递增(SEARCH_ADDEND=16),上限 64;TTFT P95 超 SLO 或 OOM 即停止。
|
||||||
|
# PD 服务常驻(deploy_pd.sh 管理),本脚本只发请求,不启停服务器。
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# DRY_RUN=1 bash run_adaptive_concurrency_pd.sh # 预览 shape + 并发序列
|
||||||
|
# bash run_adaptive_concurrency_pd.sh # 正式跑
|
||||||
|
# ISL_LIST="1024" OSL_LIST="4096" bash ... # 只跑某 shape
|
||||||
|
#
|
||||||
|
# 产物: adaptive_results/<run_id>/ (points/shapes/summary JSONL + CSV),与单组一致。
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
EXPERIMENT_NAME="$(basename "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${SCRIPT_DIR}/../../../scripts/common/lib.sh"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${SCRIPT_DIR}/../../../scripts/common/platform.sh"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${SCRIPT_DIR}/config.env"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${SCRIPT_DIR}/adaptive_config.env"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${SCRIPT_DIR}/../../../scripts/common/adaptive_bench_lib.sh"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "${SCRIPT_DIR}/../../../scripts/common/deploy_cli.sh"
|
||||||
|
|
||||||
|
# PD 服务由 deploy_pd.sh 常驻管理,本脚本不指定 TP/DP(固定 TP32×EP32)。
|
||||||
|
TP="${TP:-32}"
|
||||||
|
DP="${DP:-1}"
|
||||||
|
ENGINE="sglang"
|
||||||
|
ENGINE_PORT="$SGLANG_PORT" # router 入口 31000
|
||||||
|
RESULT_BASE="${RESULT_BASE:-${SCRIPT_DIR}/adaptive_results}"
|
||||||
|
ACTIVE_ENGINE_SERVER_LOG=""
|
||||||
|
DOCKER_IMAGE="${DOCKER_IMAGE:-${DOCKER_CLIENT_IMAGE:-lmsysorg/sglang:kimi-k3}}"
|
||||||
|
|
||||||
|
if [[ -x "${VENV_CLIENT}/bin/python" ]]; then
|
||||||
|
PYTHON="${VENV_CLIENT}/bin/python"
|
||||||
|
else
|
||||||
|
PYTHON="$(command -v python3)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# PD 常驻服务:server 生命周期函数全部 no-op(只探活,不启停)。
|
||||||
|
# adaptive_bench_lib.sh 的 engine_* 调用会被安全绕过,搜索/产物逻辑保留。
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
engine_is_healthy() {
|
||||||
|
curl --fail --silent --show-error --max-time 5 \
|
||||||
|
"http://127.0.0.1:${ENGINE_PORT}/health" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
engine_start_server() { return 0; }
|
||||||
|
engine_stop_server() { return 0; }
|
||||||
|
engine_build_server_args() { echo "PD server managed by deploy_pd.sh"; }
|
||||||
|
engine_restart_server() { return 0; }
|
||||||
|
|
||||||
|
engine_detect_oom() {
|
||||||
|
local detail_log="$1"
|
||||||
|
local pattern='CUDA out of memory|torch\.OutOfMemoryError|OutOfMemory|out of memory|OOM|RESOURCE_EXHAUSTED|Failed to allocate memory|error: [0-9]+: ERR_RESOURCE_STATE'
|
||||||
|
grep -Eiq "$pattern" "$detail_log" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
engine_run_bench() {
|
||||||
|
local isl="$1"
|
||||||
|
local osl="$2"
|
||||||
|
local concurrency="$3"
|
||||||
|
local num_prompts="$4"
|
||||||
|
local output_file="$5"
|
||||||
|
local warmup_requests
|
||||||
|
warmup_requests="$(adaptive_warmup_request_count "$concurrency")"
|
||||||
|
local -a bench_args=(
|
||||||
|
--backend sglang
|
||||||
|
--host 127.0.0.1
|
||||||
|
--port "$ENGINE_PORT"
|
||||||
|
--tokenizer "$MODEL_PATH"
|
||||||
|
--dataset-name "$BENCH_DATASET_NAME"
|
||||||
|
--random-input-len "$isl"
|
||||||
|
--random-output-len "$osl"
|
||||||
|
--random-range-ratio "$RANDOM_RANGE_RATIO"
|
||||||
|
--num-prompts "$num_prompts"
|
||||||
|
--max-concurrency "$concurrency"
|
||||||
|
--request-rate 10000
|
||||||
|
--warmup-requests "$warmup_requests"
|
||||||
|
--output-file "$output_file"
|
||||||
|
--output-details
|
||||||
|
--disable-tqdm
|
||||||
|
--flush-cache
|
||||||
|
)
|
||||||
|
if [[ "$BENCH_DATASET_NAME" == "random" ]]; then
|
||||||
|
bench_args+=(--dataset-path "$DATASET_PATH")
|
||||||
|
elif [[ "$BENCH_DATASET_NAME" == "random-ids" ]]; then
|
||||||
|
: # random-ids 不需要 --tokenize-prompt
|
||||||
|
else
|
||||||
|
bench_args+=(--tokenize-prompt)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$USE_DOCKER_CLIENT" == "1" ]]; then
|
||||||
|
local -a volume_args=(-v "${MODEL_PATH}:${MODEL_PATH}:ro" -v "${RESULT_BASE}:${RESULT_BASE}")
|
||||||
|
if [[ "$BENCH_DATASET_NAME" == "random" ]]; then
|
||||||
|
volume_args+=(-v "${DATASET_PATH}:${DATASET_PATH}:ro")
|
||||||
|
fi
|
||||||
|
docker run --rm \
|
||||||
|
--network host \
|
||||||
|
"${volume_args[@]}" \
|
||||||
|
-e PYTHONUNBUFFERED=1 \
|
||||||
|
-e HF_HUB_OFFLINE=1 \
|
||||||
|
-e TRANSFORMERS_OFFLINE=1 \
|
||||||
|
-e HF_DATASETS_OFFLINE=1 \
|
||||||
|
--entrypoint python3 \
|
||||||
|
"$DOCKER_IMAGE" \
|
||||||
|
-m "$SGLANG_BENCH_MODULE" "${bench_args[@]}"
|
||||||
|
else
|
||||||
|
"$PYTHON" -m "$SGLANG_BENCH_MODULE" "${bench_args[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
export -f engine_run_bench
|
||||||
|
|
||||||
|
export ENGINE_PORT MODEL_PATH RESULT_BASE DOCKER_IMAGE USE_DOCKER_CLIENT
|
||||||
|
export BENCH_DATASET_NAME DATASET_PATH RANDOM_RANGE_RATIO BENCH_WARMUP_MAX_REQUESTS PYTHON SGLANG_BENCH_MODULE
|
||||||
|
PARALLEL_CONFIGS=("${TP} ${DP}")
|
||||||
|
|
||||||
|
export TP DP ENGINE PARALLEL_CONFIGS
|
||||||
|
|
||||||
|
# PD 长上下文:C=16 起 +16 递增,上限 64;超 SLO 回退 C=8 -> 1。
|
||||||
|
export SEARCH_START_CONCURRENCY=16
|
||||||
|
export SEARCH_ADDEND=16
|
||||||
|
export SEARCH_INITIAL_BACKOFF_CONCURRENCIES="8 1"
|
||||||
|
# 长上下文不用整组跳过(64k 单并发 TTFT 可能就较高)。
|
||||||
|
export TTFT_GROUP_SKIP_MS="${TTFT_GROUP_SKIP_MS:-0}"
|
||||||
|
|
||||||
|
adaptive_main "$@"
|
||||||
Loading…
x
Reference in New Issue
Block a user