作者:suliuer
在开源大模型领域,DeepSeek-R1作为拥有超过600亿参数的混合专家(MoE)模型,凭借其强大的语言理解和卓越的性能表现成为当前最受关注的开源大模型之一。本文将基于官方推荐的 SGLang 推理框架,详细介绍如何使用单节点和多节点自建满血版 DeepSeek-R1 大模型。
SGlang是一个高性能推理引擎,支持混合专家(MoE)类型的大语言模型,如DeepSeek-V3/R1。SGlang 支持多节点张量并行计算,能够在多服务器上协同工作,从而满足大规模模型的部署需求。
从官方说明文档可以看出,SGLang 是 DeepSeek 官方推荐的推理框架。SGLang 和 DeepSeek 团队合作,全面支持 DeepSeek-V3 模型的 BF16 和 FP8 推理模式,同时 SGLang 还支持多节点张量并行、MLA 优化、DP Attention 等,在开源框架中提供顶级的延迟和吞吐量性能,这使得 SGLang 成为运行 DeepSeek 模型的最佳开源大模型引擎之一。
图:来自https://github.com/deepseek-ai/DeepSeek-V3。
图:来自https://github.com/sgl-project/sglang/releases。
在部署 DeepSeek-R1之前,我们先了解一下 GPU 的相关通信技术。GPU 之间的高效通信能够显著提升大模型的推理速度和资源利用率,无论是单机内部的 NVLink 和 NVSwitch,还是多机之间的 RDMA 网络技术,它们都为 GPU 的高效协同工作提供了坚实的基础。
在高性能计算和人工智能应用中,NVIDIA 开发的NVLink 和 NVSwitch 技术,用于提高服务器内部 GPU 之间的通信效率。
NVLink 是同主机内不同 GPU 之间的一种高速互联方式,用于增加 GPU 与 GPU 之间或者 GPU 与 CPU 之间的数据传输速率。它提供了比传统 PCIe 接口更高的带宽和更低的延迟,使得多个 GPU 可以高效地协同工作。
NVSwitch 则是一个扩展了 NVLink 功能的专用交换芯片,它允许在一个系统内部署更多的 GPU,并让这些 GPU 之间实现全互联 (full mesh),从而进一步提升多 GPU 系统的可扩展性和性能。NVSwitch 通过提供大量的 NVLink 端口来支持这种高度互联的架构。
图:八卡服务器 NVIDIA GPU 之间通过 NVLink互连的物理拓扑信息。
当分布式计算任务(如训练或推理大模型)跨越多个物理服务器时,RDMA(Remote Direct Memory Access)网络技术成为了提升 GPU 间通信性能的关键。
RDMA(Remote Direct Memory Access)即远程直接内存访问,是一种使数据能直接从一台计算机的内存传输到另一台计算机内存的网络传输技术,无需双方操作系统介入,可实现高吞吐、低延迟的网络通信,特别适用于大规模并行计算机集群,能有效提升应用系统性能。
图:TCP/IP与RDMA通信方式对比。
在多节点分布式推理场景中,GPU 之间需要频繁地进行数据通信以同步计算结果和传递梯度信息。传统的网络通信方式(如 TCP/IP)在这种高频率、大数据量的通信场景下存在明显的性能瓶颈,例如高延迟、低带宽和高 CPU 占用率等问题。RDMA 技术通过允许网络中的不同节点直接访问对方内存,无需 CPU 的深度参与,从而极大地降低了通信延迟和 CPU 负载,提高了数据传输的效率和带宽利用率。这对于需要在多个 GPU 之间快速传递大量数据的大模型推理任务来说是至关重要的。
对于像 DeepSeek-R1 参数量巨大的大规模语言模型,推理过程中需要处理大量的数据并进行复杂的计算。在多节点环境下,模型的不同部分分布在不同的 GPU 上,这些 GPU 之间需要高效地通信以完成整个模型的推理过程。RDMA 的低延迟和高带宽特性使得 GPU 之间的通信更加迅速和高效,从而减少了因通信延迟导致的计算资源浪费,提高了整个系统的推理速度和吞吐量。此外,RDMA 还可以减少因通信引起的 CPU 干扰,使得 CPU 能够更专注于其他计算任务,进一步提升了系统的整体性能。
DeepSeek-R1 模型下载(两种方式选择)。
# HuggingFace
git clone https://huggingface.co/deepseek-ai/DeepSeek-R1
# ModelScope
git clone https://www.modelscope.cn/deepseek-ai/DeepSeek-R1.git
SGLang 环境部署。
# conda 环境
conda create --name sglang python=3.10
conda activate sglang
# sgalng 部署
pip install "sglang[all]>=0.4.3.post2" --find-links https://flashinfer.ai/whl/cu124/torch2.5/flashinfer-python
# 一个官方 bug,目前兼容的 transformers 版本是 4.48.3
# 安装 sglang 之后 transformers 版本是 4.49,将其重装为 4.48.3
pip uninstall transformers -y
pip install transformers==4.48.3
SGLang 原生支持跨机多节点部署,下面我们分别在单节点和多节点服务器部署线上环境满血版 DeepSeep-R1大模型。
服务器环境:NVIDIA H20(96G)*8*1。
# DeepSeek-R1-671B 单节点部署
python3 -m sglang.launch_server \
--model-path /data/llm/DeepSeek-R1 \
--served-model-name DeepSeek-R1 \
--tp 8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--mem-fraction-static 0.95 \
--max-running-requests 32 \
--context-length 65536 \
--quantization fp8 \
--chunked-prefill-size 4096
参数说明:
--model-path /data/llm/DeepSeek-R1
指定模型权重文件的本地路径,SGLang 从该目录加载模型结构与权重。
--served-model-name DeepSeek-R1
自定义 API 中显示的模型名称,与客户端请求的 model 字段匹配。
--trust-remote-code
信任远程代码,允许加载模型目录中的自定义代码(如 modeling_deepseek.py)。
--tp 8
启用 8 路张量并行(Tensor Parallelism)实现并行处理,提高推理速度。
--host 0.0.0.0 --port 30000
服务监听所有 IP 的 30000 端口,支持跨机器访问。
--mem-fraction-static 0.95
预留 95% 显存用于模型计算,5% 动态分配防止碎片,并发场景可降至 0.8-0.9,若出现 OOM 需降低该值。
--context-length 65536
设置模型支持的最大上下文长度(64K)
--chunked-prefill-size 1024
将长输入分块处理(每块 1024 Token),避免 OOM 并提升计算效率。64K 上下文推荐 1024-4096,过小会增加调度开销。
--quantization fp8
指定模型的量化精度为 FP8,DeepSeek-R1 原生版本的模型权重为 FP8 数据格式。
--max-running-requests 32
限制并发处理请求数,防止显存过载。
多节点部署的前置条件与单机部署一致,每个节点均需提前下载好模型文件,然后在每个节点执行启动命令。启动命令时,先启动主节点,再启动剩余节点。在服务启动后,发起请求时需指定为主节点 IP。
服务器环境:NVIDIA H20(96G)*8*2,RDMA 通信。
# DeepSeek-R1-671B 分布式多节点部署
# 第一个节点
python3 -m sglang.launch_server \
--model-path /data/llm/DeepSeek-R1 \
--served-model-name DeepSeek-R1 \
--tp 16 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--mem-fraction-static 0.95 \
--max-running-requests 64 \
--context-length 131072 \
--quantization fp8 \
--chunked-prefill-size 2048 \
--dist-init-addr 10.10.10.10:40000 \
--nnodes 2 \
--node-rank 0
# 第二个节点
python3 -m sglang.launch_server \
--model-path /data/llm/DeepSeek-R1 \
--served-model-name DeepSeek-R1 \
--tp 16 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--mem-fraction-static 0.95 \
--max-running-requests 64 \
--context-length 131072 \
--quantization fp8 \
--chunked-prefill-size 2048 \
--dist-init-addr 10.10.10.10:40000 \
--nnodes 2 \
--node-rank 1
参数说明:
--dist-init-addr 10.x.x.x:40000:
用于指定分布式推理的初始化地址。在分布式部署中,所有节点需要通过这个地址进行通信和同步。主节点通过这个地址初始化分布式环境,其他节点通过这个地址连接到主节点,从而实现分布式推理。可以设置为第一台启动节点的 IP。
--nnodes 2
指定整个分布式推理集群中的总节点数。例如,如果使用两台机器进行分布式推理,则该的值应为 2。
--node-rank
指定当前节点在分布式训练中的排序(ID)。这个排名是从 0 开始的整数,例如在两节点的集群中,第一个节点的 --node-rank 为 0,第二个节点的 --node-rank 为 1。
作为对照,我们使用四节点服务器(每台服务器 H20*2,共 8 卡),基于普通网络分布式部署满血版 DeepSeep-R1。
服务器环境:H20*2*4
GLOO_SOCKET_IFNAME=eth0
,该参数是分布式通信的环境变量配置,用于显式指定分布式推理中节点间通信使用的网络接口。# DeepSeek-R1-671B
# 第一个节点
GLOO_SOCKET_IFNAME=eth0 python3 -m sglang.launch_server \
--model-path /disk2/llm/DeepSeek-R1/ \
--served-model-name DeepSeek-R1 \
--tp 8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--dist-init-addr 10.10.10.10:40000 \
--mem-fraction-static 0.95 \
--disable-cuda-graph \
--nnodes 4 \
--node-rank 0
# 第二个节点
GLOO_SOCKET_IFNAME=eth0 python3 -m sglang.launch_server \
--model-path /disk3/llm/DeepSeek-R1/ \
--served-model-name DeepSeek-R1 \
--tp 8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--dist-init-addr 10.10.10.10:40000 \
--mem-fraction-static 0.95 \
--disable-cuda-graph \
--nnodes 4 \
--node-rank 1
# 第三个节点
GLOO_SOCKET_IFNAME=eth0 python3 -m sglang.launch_server \
--model-path /disk2/llm/DeepSeek-R1/ \
--served-model-name DeepSeek-R1 \
--tp 8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--dist-init-addr 10.10.10.10:40000 \
--mem-fraction-static 0.95 \
--disable-cuda-graph \
--nnodes 4 \
--node-rank 2
# 第四个节点
GLOO_SOCKET_IFNAME=eth0 python3 -m sglang.launch_server \
--model-path /disk2/llm/DeepSeek-R1/ \
--served-model-name DeepSeek-R1 \
--tp 8 \
--host 0.0.0.0 \
--port 30000 \
--trust-remote-code \
--dist-init-addr 10.10.10.10:40000 \
--mem-fraction-static 0.95 \
--disable-cuda-graph \
--nnodes 4 \
--node-rank 3
运行状况
启动大模型时长:大约 40-60 分钟;
curl 代码:
# curl 代码
curl -X POST http://localhost:30000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "DeepSeek-R1",
"messages": [
{
"role": "user",
"content": "你好,你是谁?"
}
],
"stream": true,
"temperature": 0.6
}'
python 代码:
# OpenAI 标准接口
from openai import OpenAI
client = OpenAI(api_key="<DeepSeek API Key>", base_url="http://localhost:30000/v1/")
response = client.chat.completions.create(
model="DeepSeek-R1",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "写一首散文诗。"},
],
stream=True
)
for chunk in response:
print(chunk.choices[0].delta.content, end="", flush=True)
下载基准测试参考的数据集 ShareGPT_V3_unfiltered_cleaned_split.json (ShareGPT V3清洗版),SGLang 的基准测试通常基于此数据集评估模型在多样化对话场景下的性能。
# 下载评估数据集
git lfs clone https://www.modelscope.cn/datasets/gliang1001/ShareGPT_V3_unfiltered_cleaned_split.git
使用 sglang.bench_serving 进行性能测试。
# 性能测试命令
python3 -m sglang.bench_serving --backend sglang --dataset-name random --random-range-ratio 1 --tokenizer /data/llm/DeepSeek-R1 --host 127.0.0.1 --port 30000 --output-file "ds-r1-bench.json" --dataset-path ./ShareGPT_V3_unfiltered_cleaned_split.json --random-input 1000 --random-output 3000 --max-concurrency 1 --num-prompts 32
# 输出
============ Serving Benchmark Result ============
Backend: sglang
Traffic request rate: inf
Max reqeuest concurrency: 1
Successful requests: 32
Benchmark duration (s): 3513.98
Total input tokens: 32000
Total generated tokens: 96000
Total generated tokens (retokenized): 95703
Request throughput (req/s): 0.01
Input token throughput (tok/s): 9.11
Output token throughput (tok/s): 27.32
Total token throughput (tok/s): 36.43
Concurrency: 1.00
----------------End-to-End Latency----------------
Mean E2E Latency (ms): 109811.32
Median E2E Latency (ms): 107513.41
---------------Time to First Token----------------
Mean TTFT (ms): 348.89
Median TTFT (ms): 346.58
P99 TTFT (ms): 408.93
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms): 36.50
Median TPOT (ms): 35.74
P99 TPOT (ms): 44.16
---------------Inter-token Latency----------------
Mean ITL (ms): 36.50
Median ITL (ms): 35.95
P99 ITL (ms): 46.25
==================================================
SGLang 测试对比 输入:1K 输出:3K | ||||||
并发数 | 输出 token 速率(tokens/s) | 平均首 token 时延 TTFT(s) | 每分钟查询次数 QPM | |||
单机八卡 | 四机八卡 | 单机八卡 | 四机八卡 | 单机八卡 | 四机八卡 | |
1 | 27.32 | 5.30 | 0.349 | 5.570 | 0.55 | 0.106 |
20 | 234.86 | 83.26 | 2.718 | 76.095 | 4.697 | 1.67 |
25 | 245.25 | 90.29 | 3.276 | 89.578 | 4.904 | 1.806 |
32 | 382.01 | 107.47 | 4.917 | 103.616 | 7.64 | 2.149 |
使用程序实际并发请求(并发数30),四节点八卡成功处理请求数少 40%,且平均耗时多一倍。
图:四节点八卡和单节点八卡实际请求对比。
从基准测试结果来看,单机八卡在各个并发数下的性能均显著优于四机八卡 H20(非 RDMA 通信)。具体表现在:
结论:单机八卡凭借其内部高效的通信机制(如 NVLink),在推理性能上具有显著优势。四机八卡由于仅使用普通以太网通信,跨节点通信开销吞噬了多机扩展的理论收益,通信效率低下,导致整体性能较差。在实际应用中,若对推理性能有较高要求,建议优先选择单机多卡部署方式;若需多机部署,应考虑配置 RDMA 网络以提升通信效率。
DeepSeek-R1 官方模型部署之后会有一定机率丢失思考过程。前段时间 DeepSeek-R1 官方修改了配置文件的聊天模板,在 tokenizer_config.json 文件的 chat_template 字段加了 <think>\\n
,该字段可以强制使回答有思考过程:
# 原来
{{'<|Assistant|>'}}
# 修改之后
{{'<|Assistant|><think>\\n'}}
过实测对比:
<think>\\n
开头的,所有正常请求的 100% 都会输出思考过程,就是会丢失 <think>
左标签(可以通过在调用之后补全);<think>\\n
的,则有可能会丢失思考过程(特别是简单问题),丢失率 大约45%。图:添加模板是否添加<think>\\n 对比。
参考:https://huggingface.co/deepseek-ai/DeepSeek-R1/commit/8a58a132790c9935686eb97f042afa8013451c9f
RuntimeError: Gloo connectFullMesh failed with
[rank0]:[E304 22:28:11.132616482 ProcessGroupGloo.cpp:143] Gloo connectFullMesh failed with [../third_party/gloo/gloo/transport/tcp/pair.cc:144] no error
[2025-03-04 22:28:11 TP0] Scheduler hit an exception: Traceback (most recent call last):
File "/data/miniconda3/root/envs/sglang/lib/python3.10/site-packages/sglang/srt/managers/scheduler.py", line 1816, in run_scheduler_process
scheduler = Scheduler(server_args, port_args, gpu_id, tp_rank, dp_rank)
...
backend_class = ProcessGroupGloo(
RuntimeError: Gloo connectFullMesh failed with [../third_party/gloo/gloo/transport/tcp/pair.cc:144] no error
[2025-03-04 22:28:11] Received sigquit from a child proces. It usually means the child failed.
Killed
解决:添加参数 GLOO_SOCKET_IFNAME=eth0,基于以太网 socket 通信。
GLOO_SOCKET_IFNAME=eth0 python3 -m sglang.launch_server --model-path /disk1/llm/DeepSeek-R1-Distill-Qwen-1.5B --served-model-name DeepSeek-R1-1.5B --tp2--host0.0.0.0 --port30001--trust-remote-code--dist-init-addr10.91.4.9:40000 --nnodes2--node-rank0
cannot import name ‘is_valid_list_of_images’
解决:参考:https://github.com/sgl-project/sglang/issues/3878
pip uninstall transformers
pip install transformers==4.48.3
assert self.total_num_heads % tp_size == 0
AssertionError
该错误是因为张量并行数(tp_size)与模型注意力头数不匹配导致的。查看大模型目录中config.json 文件的 num_attention_heads
字段,调整张量并行的数量能被该字段整除即可。
在基于 SGLang 分布式多机部署满血版 DeepSeek-R1 时,需要提前规划好服务器总节点数量和 GPU 数量,然后根据规划好的信息配置启动参数,比如 GPU 张量并行数量(–tp)和总节点数量(–nnodes)等。如果需要对集群进行扩容,通常的做法是增加新的 GPU 集群,然后通过负载均衡机制,将请求合理地分配到多个 GPU 集群上,以充分利用新增的计算资源,提高整个系统的处理能力。
本文详细介绍了基于 SGLang 框架自建 DeepSeek-R1 满血版的全过程,从环境搭建到模型部署,再到性能评估与问题解决。通过 SGLang 强大的多节点张量并行计算能力,我们能够高效地部署和运行 DeepSeek-R1 这样参数量巨大的模型,并在实际应用中展现出卓越的推理性能。下来我们会持续跟进最新的开源大模型前沿技术发展,为应用的快速落地和性能提升提供更有力的支持。