Qwen3.5 模型部署
本章节包含 Qwen3.5 系列模型的部署脚本,脚本涉及的参数说明、PD 分离一键部署说明见 快速开始。
-
参考 环境准备 进行环境检查、启动容器。
-
容器镜像地址参考 版本发布信息-镜像地址。
-
PD分离脚本涉及的参数说明和一键运行说明见 快速开始。
-
参考 环境准备-RDMA 网卡检测 中的脚本,请其保存为
resolve_sglang_pd_ib_devices.sh,与 SGLang 服务启动脚本放在同一路径下。 -
部分脚本用到 的
EPLB_FILE是利用测试数据场景进行录制,可联系支持工程师获取。实际生产部署请自行录制,也可删除EPLB_FILE环境变量及 SGLang 启动参数中的init-expert-location。
Qwen3.5-0.8B/2B/4B/9B
本示例以 1卡(TP1)部署 Qwen3.5-9B。脚本同样适用于 Qwen3.5-0.8B/2B/4B 模型,注意修改模型名和权重路径。
启动脚本 qwen35_9b_server.sh
#!/usr/bin/env bash
set -euo pipefail
MODEL_NAME="${MODEL_NAME:-Qwen3.5-9B}"
MODEL_PATH="${MODEL_PATH:-/data/models/Qwen3.5-9B/}"
TP_SIZE="${TP_SIZE:-1}"
PP_SIZE="${PP_SIZE:-1}"
EP_SIZE="${EP_SIZE:-}"
MEM_FRACTION_STATIC="${MEM_FRACTION_STATIC:-0.55}"
CUDA_GRAPH_BS_MAX="${CUDA_GRAPH_BS_MAX:-128}"
MOE_RUNNER_BACKEND="${MOE_RUNNER_BACKEND:-}"
DISABLE_OVERLAP_SCHEDULE="${DISABLE_OVERLAP_SCHEDULE:-1}"
DISABLE_PIECEWISE_CUDA_GRAPH="${DISABLE_PIECEWISE_CUDA_GRAPH:-0}"
SERVED_MODEL_NAME="${SERVED_MODEL_NAME:-${MODEL_NAME}}"
SGLANG_VENV="${SGLANG_VENV:-/root/.virtualenvs/sglang-default}"
SGLANG_PYTHON="${SGLANG_PYTHON:-${PYTHON:-${SGLANG_VENV}/bin/python3}}"
if [[ -f "${SGLANG_VENV}/bin/activate" ]]; then
# shellcheck disable=SC1091
source "${SGLANG_VENV}/bin/activate"
fi
HOST="${HOST:-${SGLANG_HOST:-0.0.0.0}}"
PORT="${PORT:-${SGLANG_PORT:-32289}}"
DIST_PORT="${DIST_PORT:-2452}"
CHUNKED_PREFILL_SIZE="${CHUNKED_PREFILL_SIZE:--1}"
ENABLE_CACHE_REPORT="${ENABLE_CACHE_REPORT:-0}"
TOKENIZER_BACKEND="${TOKENIZER_BACKEND:-fastokens}"
HEALTH_WAIT_SECONDS="${HEALTH_WAIT_SECONDS:-900}"
export PATH="${SGLANG_VENV}/bin:${PATH}"
export LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:/usr/local/musa/lib:/usr/local/openmpi/lib:/usr/local/musa/mudnn/lib:/usr/local/mtshmem/lib:${LD_LIBRARY_PATH:-}"
export MUSA_VISIBLE_DEVICES="${MUSA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}"
export MTHREADS_VISIBLE_DEVICES="${MTHREADS_VISIBLE_DEVICES:-${MUSA_VISIBLE_DEVICES}}"
export MUSA_LAUNCH_BLOCKING="${MUSA_LAUNCH_BLOCKING:-0}"
export MUSA_ENABLE_LLC_OPT="${MUSA_ENABLE_LLC_OPT:-1}"
export MCCL_IB_GID_INDEX="${MCCL_IB_GID_INDEX:-3}"
export MCCL_NET_SHARED_BUFFERS="${MCCL_NET_SHARED_BUFFERS:-0}"
export MCCL_PROTOS="${MCCL_PROTOS:-2}"
export GLOO_SOCKET_IFNAME="${GLOO_SOCKET_IFNAME:-bond0}"
export TP_SOCKET_IFNAME="${TP_SOCKET_IFNAME:-bond0}"
export VLLM_PATCH_MUSA_CUSTOM_OPS="${VLLM_PATCH_MUSA_CUSTOM_OPS:-1}"
export SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN="${SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN:-1}"
export SGLANG_SET_CPU_AFFINITY="${SGLANG_SET_CPU_AFFINITY:-1}"
export SGLANG_USE_DEEPGEMM_BMM="${SGLANG_USE_DEEPGEMM_BMM:-0}"
export SGLANG_MOE_PADDING="${SGLANG_MOE_PADDING:-1}"
export SGLANG_USE_MUSA_FUSED_KERNEL="${SGLANG_USE_MUSA_FUSED_KERNEL:-1}"
[[ -d "${MODEL_PATH}" ]] || {
echo "MODEL_PATH does not exist: ${MODEL_PATH}" >&2
exit 2
}
[[ -x "${SGLANG_PYTHON}" ]] || {
echo "SGLANG_PYTHON not executable: ${SGLANG_PYTHON}" >&2
exit 2
}
WORK_HOME="${WORK_HOME:-$PWD}"
CURRENT_TIME="$(date '+%Y%m%d_%H%M%S')"
LOG_DIR="${LOG_DIR:-${WORK_HOME}/logs/service/${MODEL_NAME}/accuracy/${CURRENT_TIME}}"
LOG_FILE="${LOG_FILE:-${LOG_DIR}/sglang_$(date '+%Y%m%d_%H%M%S').log}"
PID_FILE="${PID_FILE:-${LOG_FILE}.pid}"
CMD_FILE="${CMD_FILE:-${LOG_FILE}.cmd}"
ENV_FILE="${ENV_FILE:-${LOG_FILE}.env}"
mkdir -p "${LOG_DIR}" "${WORK_HOME}/traces"
MASTER_IP="$(hostname -I | awk '{print $1}')"
MASTER_IP="${MASTER_IP:-127.0.0.1}"
if command -v lsof >/dev/null 2>&1; then
mapfile -t old_pids < <(lsof -ti:"${PORT}" || true)
if ((${#old_pids[@]} > 0)); then
echo "killing existing processes on port ${PORT}: ${old_pids[*]}"
kill -9 "${old_pids[@]}" || true
fi
fi
pkill -9 -f "[s]glang.launch_server.*--port[[:space:]]+${PORT}" || true
pkill -9 -f "[s]glang.launch_server.*${MODEL_PATH}" || true
sleep 3
cd /sgl-workspace/sglang
cmd=(
"${SGLANG_PYTHON}" -m sglang.launch_server
--model-path "${MODEL_PATH}"
--served-model-name "${SERVED_MODEL_NAME}"
--trust-remote-code
--tp-size "${TP_SIZE}"
--pp-size "${PP_SIZE}"
--host "${HOST}"
--port "${PORT}"
--dist-init-addr "${MASTER_IP}:${DIST_PORT}"
--nnodes 1
--node-rank 0
--attention-backend fa3
--mm-attention-backend fa3
--linear-attn-backend flashinfer
--sampling-backend flashinfer
--moe-runner-backend auto
--tokenizer-backend fastokens
--mem-fraction-static "${MEM_FRACTION_STATIC}"
--cuda-graph-bs $(seq 1 "${CUDA_GRAPH_BS_MAX}")
--mamba-scheduler-strategy extra_buffer
--chunked-prefill-size "${CHUNKED_PREFILL_SIZE}"
--decode-log-interval 1
--skip-server-warmup
)
if [[ -n "${EP_SIZE}" ]]; then
cmd+=(--ep-size "${EP_SIZE}")
fi
if [[ -n "${MOE_RUNNER_BACKEND}" ]]; then
cmd+=(--moe-runner-backend "${MOE_RUNNER_BACKEND}")
fi
if [[ -n "${TOKENIZER_BACKEND}" ]]; then
cmd+=(--tokenizer-backend "${TOKENIZER_BACKEND}")
fi
if [[ "${DISABLE_OVERLAP_SCHEDULE}" == "1" || "${DISABLE_OVERLAP_SCHEDULE}" == "true" ]]; then
cmd+=(--disable-overlap-schedule)
fi
cmd+=(--disable-piecewise-cuda-graph)
if [[ "${ENABLE_CACHE_REPORT}" == "1" || "${ENABLE_CACHE_REPORT}" == "true" ]]; then
cmd+=(--enable-cache-report)
fi
if declare -p EXTRA_ARGS >/dev/null 2>&1; then
cmd+=("${EXTRA_ARGS[@]}")
fi
cmd+=(
--reasoning-parser qwen3
--tool-call-parser qwen3_coder
)
{
echo "timestamp=$(date '+%F %T %z')"
echo "model_name=${MODEL_NAME}"
echo "served_model_name=${SERVED_MODEL_NAME}"
echo "model_path=${MODEL_PATH}"
echo "host=${HOST}"
echo "port=${PORT}"
echo "tp_size=${TP_SIZE}"
echo "pp_size=${PP_SIZE}"
echo "ep_size=${EP_SIZE}"
echo "cuda_graph_bs=1..${CUDA_GRAPH_BS_MAX}"
echo "python=${SGLANG_PYTHON}"
env | sort | grep -E '^(LD_LIBRARY_PATH|MUSA_|MTHREADS_|MCCL_|GLOO_|TP_SOCKET|VLLM_|SGLANG_)=' || true
} >"${ENV_FILE}"
printf '%q ' "${cmd[@]}" >"${CMD_FILE}"
printf '\n' >>"${CMD_FILE}"
echo "starting ${MODEL_NAME} for GSM8K concurrency 128"
echo "model: ${MODEL_PATH}"
echo "port: ${PORT}"
echo "log: ${LOG_FILE}"
echo "cmd: ${CMD_FILE}"
if [[ "${FOREGROUND:-0}" == "1" ]]; then
exec "${cmd[@]}"
fi
nohup "${cmd[@]}" >"${LOG_FILE}" 2>&1 </dev/null &
server_pid=$!
echo "${server_pid}" >"${PID_FILE}"
disown "${server_pid}" 2>/dev/null || true
echo "pid=${server_pid}"
for _ in $(seq 1 "${HEALTH_WAIT_SECONDS}"); do
if ! kill -0 "${server_pid}" 2>/dev/null; then
echo "server process exited before health check passed; tailing log" >&2
tail -200 "${LOG_FILE}" >&2 || true
exit 1
fi
curl -sf --max-time 5 "http://127.0.0.1:${PORT}/health" >/dev/null && {
echo "health OK on port ${PORT}"
exit 0
}
sleep 1
done
echo "server did not become healthy within ${HEALTH_WAIT_SECONDS}s; tailing log" >&2
tail -200 "${LOG_FILE}" >&2 || true
exit 1
Qwen3.5-27B
本示例使用 2卡(TP2) 部署, 也设置 --tp-size 1 进行单卡部署。
启动脚本 qwen35_27b_server.sh
#!/bin/bash
SGLANG_VENV="${SGLANG_VENV:-$HOME/.virtualenvs/sglang-default}"
SGLANG_PYTHON="${SGLANG_PYTHON:-${SGLANG_VENV}/bin/python3}"
SGLANG_HOST="${SGLANG_HOST:-0.0.0.0}"
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:/usr/local/musa/lib:$LD_LIBRARY_PATH
export MUSA_LAUNCH_BLOCKING=0
export MUSA_ENABLE_LLC_OPT=1
export MCCL_IB_GID_INDEX=3
export MCCL_NET_SHARED_BUFFERS=0
export MCCL_PROTOS=2
export GLOO_SOCKET_IFNAME=bond0
export TP_SOCKET_IFNAME=bond0
export VLLM_PATCH_MUSA_CUSTOM_OPS=1
SGLANG_ENABLE_SPECULATIVE="${SGLANG_ENABLE_SPECULATIVE:-1}"
# 清理缓存
rm -rf ~/.triton/cache
rm -rf /tmp/*
# pkill -f "sgl.*"
# mthreads-gmi | grep -E '^[0-9]+\s+[0-9]+\s+' | awk '{print $2}' |
#sort -u | xargs kill -9
# sleep 3
get_master_ip() {
local hostname_ip=$(hostname -I 2>/dev/null | awk '{print $1}')
if [ -n "$hostname_ip" ] && [ "$hostname_ip" != "127.0.0.1" ]; then
echo "$hostname_ip"
return
fi
}
CURRENT_TIME=$(date "+%Y%m%d_%H%M%S")
SGLANG_PORT="${SGLANG_PORT:-31000}"
#MASTER_IP=127.0.0.1
MASTER_IP=$(get_master_ip)
NODE_RANK=0
WORLD_SIZE=1
WORK_HOME="$PWD"
LOG_DIR=$WORK_HOME/output/$CURRENT_TIME/
mkdir -p "$LOG_DIR"
export SGLANG_TORCH_PROFILER_DIR=$WORK_HOME/traces
MODEL_PATH=/data/models/Qwen3.5-27B-FP8/
cmd=(
"$SGLANG_PYTHON" -m sglang.launch_server
--model-path ${MODEL_PATH}
--trust-remote-code
--cuda-graph-bs $(seq 1 32)
--disable-piecewise-cuda-graph
--disable-overlap-schedule
--tp-size 2
--pp-size 1
--mem-fraction-static 0.78
--attention-backend fa3
--linear-attn-backend flashinfer
--tokenizer-backend fastokens
--enable-cache-report
--mm-attention-backend fa3
--moe-runner-backend auto
--sampling-backend flashinfer
--dist-init-addr ${MASTER_IP}:50022
--nnodes ${WORLD_SIZE}
--node-rank ${NODE_RANK}
--chunked-prefill-size 4096
--mamba-scheduler-strategy extra_buffer
--max-running-requests 32
--max-prefill-tokens 8192
--context-length 16384
--port ${SGLANG_PORT}
--host "${SGLANG_HOST}"
--decode-log-interval 1
--reasoning-parser qwen3
--tool-call-parser qwen3_coder
)
if [[ "$SGLANG_ENABLE_SPECULATIVE" == "1" ]]; then
cmd+=(
--speculative-algo NEXTN
--speculative-num-steps 1
--speculative-eagle-topk 1
--speculative-num-draft-tokens 2
)
fi
nohup "${cmd[@]}" > "${LOG_DIR}/${MASTER_IP}_$(date '+%Y%m%d_%H%M%S').log" 2>&1 &
echo -e "Main log file: \033[34m$LOG_DIR\033[0m"