ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

DeepSeek国产超节点推理部署:从显存预算到吞吐调优的完整路径

DeepSeek国产超节点推理部署:从显存预算到吞吐调优的完整路径

前几个月帮一个团队做国产超节点上的推理服务压测,遇到一个特别典型的现象:模型权重从主流生态转过来之后,基础功能是通的,但吞吐死活上不去,P99延迟也一直在跳。查到最后,问题根源不在模型本身,而在我们对国产加速卡的互联拓扑和显存管理方式太不敏感。

说实话,推理侧算力爆发这种趋势喊了很久,但真正落到“DeepSeek这类模型跑在国产超节点上”的时候,很多优化经验是不能直接照搬的。模型结构是公开的,权重也拿得到,但硬件的脾气不一样。这几个月我陆续整理了一套从部署到调优的实操路线,现在补全细节分享出来,希望能帮到正在做国产化推理落地的朋友。

1. 推理算力爆发的底层信号:先想清楚“为什么调整部署策略”

1.1 推理负载的结构性增长正在改变集群设计逻辑

过去大家谈算力,默认指的是训练。训练阶段对吞吐、Batch Size、梯度同步这些指标高度敏感,集群设计也围着它们转。但这两年多模态大模型和Agent类应用起来了之后,推理侧的请求量增长得非常快。最典型的特点就是“短请求、高频次、动态并发”——用户过来的问题长短不一,上下文长度飘忽不定,空闲时没人调用,热点一来整个集群被塞满。

这意味着推理集群的设计逻辑和训练是两套思路。训练关心的是“多少个Token每秒能算完”,推理关心的是“给定并发和延迟约束下,显存能不能装下KV Cache,吞吐能不能压到业务能接受的P99”。后者跟调度层和硬件条带的关系更紧密。我们之所以要在国产超节点上重新审视部署策略,就是因为这套逻辑里,硬件的形态直接决定了你能用什么样的优化手段。

1.2 DeepSeek模型的架构特征放大了哪些资源压力

DeepSeek系列模型比较有代表性的一点是MoE结构。这类模型不是每个Token激活全部参数,而是通过路由只激活部分专家。好处是单Token的计算量相对低,但问题在于参数量很大,而且专家分布在不同的计算单元上。训练阶段这种结构是为了提升训练效率,推理阶段却带来了更复杂的通信需求:每次Token都要通过路由找到专家,如果专家被切分到不同节点或者不同加速卡上,跨卡通信的频次和时延会对在线推理造成直接影响。

另一层压力来自长上下文。DeepSeek在长文本理解上的表现不错,但这会放大KV Cache的显存占用。推理服务往往要同时处理几十路请求,每路请求的KV Cache叠起来,占的显存可能比权重本身还要多。我们在部署时做的很多优化,其实都是围绕着“KV Cache能省一点是一点”和“通信开销能压一压就压一压”这两个目标展开的。

2. 国产超节点的硬件画像:部署前必须先搞清楚的四个参数

2.1 算力指标不等于有效吞吐

很多团队拿到国产加速卡的规格表,看到FP16算力数值挺高,就觉得推理能力肯定不差。但实际测下来,单卡算力只决定上限,真正影响推理吞吐的往往是显存带宽和卡间互联。

推理任务里有大量的矩阵乘和Attention计算,这类算子对显存带宽极其敏感,尤其是逐Token解码阶段,算力可能还闲着,显存带宽已经跑满了。这一点在国产超节点上尤为明显,因为不同批次的加速卡对HBM带宽的配置差异很大。部署前最好用一个小模型先测一下“单卡千Token解码延迟”,不要只看算力峰值。

2.2 互联拓扑决定能不能跑专家并行

MoE模型在推理阶段有两种部署选择:一种是把所有专家塞进单卡,另一种是把专家切分到多张卡上。单卡方案通信开销最小,但显存可能装不下;跨卡方案能解决显存容量,但Token经过路由之后需要跨卡获取专家计算结果,这个路径上的每一次转发都在烧时延。

国产超节点内部通常会提供高速互联,但具体是全网状拓扑,还是分层交换,直接决定你对“专家并行”这种策略的期望值。我的建议是,拿到环境以后先跑一遍全卡AllReduce测试,把不同卡之间的实际带宽拉出来看看。如果卡间带宽低于某个水平,MoE模型就不适合跨太多卡,尽量把切分控制在机内或超节点内的一小组卡上。

2.3 显存容量与地址空间边界

推理部署绕不开“显存够不够”的问题。很多国产加速卡的显存是统一寻址的,和设备内存之间有高带宽拷贝通道,这个概念和传统GPU的主机显存异构模式不完全一样。这会影响权重加载和缓存策略。我们在一个模拟项目里就碰到过这种情况:权重加载走统一寻址路径之后,发现CPU侧和加速卡侧的耗时分布完全变了,沿用旧的加载策略会让服务启动时间变得很长。

所以部署前一定要看硬件手册里的内存模型,搞清楚哪些数据可以留在设备端、哪些需要主存和显存之间搬来搬去。如果容易混淆,可以直接用一个小脚本来测权重加载耗时和KV Cache分配耗时,用数据来校准你的预期。

2.4 多实例切分支持程度

推理服务通常不可能独占整卡,尤其在生产环境里,一张卡上会同时跑多个实例。国产加速卡对不同推理框架的MIG/多实例支持程度不一样,有的只支持固定切分比例,有的支持更灵活的内存和算力隔离。如果准备上高并发的在线服务,要提前确认目标框架在国产卡上的多实例能力,否则后面运维会很痛苦。

3. DeepSeek模型在国产超节点上的部署实操路径

3.1 权重转换与格式对齐

当前大多数开源模型权重还是以主流深度学习框架的格式传播,但国产加速卡的原生推理引擎大多有自己的权重格式,不能直接吃原生PyTorch权重。部署的第一步通常是把权重转成目标引擎支持的格式。

转换过程里容易踩的坑是数值分布检查和版本对齐。我建议转换前先统计权重的均值和标准差,转换后做一次采样比对,避免某个算子因为精度截断导致太多激活值变成0。另一个常见的坑是分词器版本不一致。有次我们换了分词器之后,解码结果总是多出奇怪的token,后来发现是词表排序没对齐。这种问题不会直接报错,只会让输出悄悄变烂,很难排查。

3.2 张量并行与专家并行的切分方案推演

DeepSeek这种MoE模型切分时,要注意区分Attention部分和专家部分的切分策略:

  • Attention部分适合做张量并行,因为多头注意力天然可以按头切分,通信开销相对可控。
  • 专家部分则更适合做专家并行,也就是按专家维度把不同的专家放到不同的卡上。
  • 路由层的输出需要做一次All-to-All通信,把Token分发到对应专家的位置。

理论上这个逻辑不复杂,但真正做切分的时候,要面对的是“通信粒度”问题。每次Token请求都要走一次All-to-All,通信次数多、单次数据量小,这种模式对互联延迟特别敏感。

我给一个参考经验:在国产超节点上,如果单张卡能装下全部权重,优先级最高的方案是“单卡内完成所有专家计算”,完全避免跨卡专家通信。只有当单卡显存确实撑不住时,才考虑把专家分到两张卡上,并且尽量让切分后同一次前向计算中每个Token最多只跨一次卡。跨卡次数一旦多起来,延迟会指数级恶化,吞吐直接崩。

3.3 推理服务的启动参数和显存预分配

部署阶段给的启动参数其实是在帮引擎“提前规划”。比如最大序列长度、最大批次、预分配显存的buffer大小。这些参数设置得越准确,运行时就越少触发显存动态申请,整体延迟越稳定。

这里要特别注意“静态显存预留”和“动态显存伸缩”的取舍。在国产超节点上,动态显存分配的开销往往比通用GPU环境更大,因为底层的内存管理对大块连续分配的优化程度不一样。所以我们通常把最大序列长度和KV Cache容量在启动时一次性预分配到位,宁可牺牲一点显存利用率,也要换运行时的稳定。

启动参数里还有一项容易被忽略:针对多卡推理的通信buffer。有些框架默认给通信库分配的缓冲区太小,请求一多就直接排队,表现为吞吐曲线在某个并发之后突然断崖式下跌。这个参数调大之后,通常会有非常明显的提升。

4. 效率优化技巧:照着瓶颈清单一项项来

4.1 先算KV Cache预算是百发百中的前提

显存优化不能靠感觉,得用公式。单条请求KV Cache占用的显存大概可以这样估算:

显存占用 = 2(K和V两组缓存) × 层数 × 单层KV维度 × 精度字节数 × 序列长度

比如一个50层模型的单层KV维度是256,用BF16(2字节)来存,输入输出长度加到4096,那么单个请求的KV Cache大概是:

2 × 50 × 256 × 2 × 4096 = 209,715,200字节 ≈ 200MB

听起来不多,但如果同时跑256路请求,这就是50GB。也就是说,光KV Cache就能吃掉一张中等显存卡的大半容量。算清楚这笔账之后,你自然会理解为什么要对最大并发和最大长度设硬上限,也会明白量化KV Cache、共享前缀这类优化手段到底值多少钱。

4.2 量化选型:INT8依然是高性价比选择,FP8要慎用

量化是降低显存占用和提升吞吐最直接的手段之一。但量化不是万能的,模型不同层对量化的敏感度差异很大。

  • INT8量化:最成熟,对大多数模型精度影响可控,在国产加速卡上算子支持相对完整,是我们项目里用得最多的方案。
  • FP8量化:理论精度比INT8好,但很多国产加速卡的FP8算子还在迭代中,部分算子会回退到FP16计算,收益没那么明显。
  • INT4量化:显存节省很夸张,但实测里精度抖动明显,只适合对质量要求不高的场景。

我的建议是:如果以稳定上线为目标,优先INT8;如果目标是把单卡并发拉高,可以考虑对Attention层加INT8量化、对FFN层保持更高精度的混合量化方案。不要在模型的所有层上无差别套同一个量化档位,性价比太低。

4.3 连续批处理:吞吐提升最明显、却最容易配错

在线推理场景里,最有效的吞吐优化不是模型层面的,而是调度层面的连续批处理。

传统批处理是“凑够一批请求,一起开始一起结束”,中间一旦有某个请求生成了结束标记,整个batch也要等它结束才能把其他请求的slot让出来,浪费严重。连续批处理则在每个Token生成步骤结束后动态调整batch,把已经结束的请求从batch中移出,再加入新请求。这个策略在长尾请求分布(大部分请求很短、少数请求很长)下收益特别大。

但连续批处理也有配置陷阱。最常见的两个问题是“最大批大小设太小导致队列堆积”和“请求长度差异太大导致长请求不断占住slot”。后者在国产超节点上尤其突出,因为我们试过一版配置,短请求延迟被个别长文档拉长了好几百毫秒。解决办法是在入口设置两个队列,一个给短请求、一个给长请求,分别限制并发和最大等待时间,效果立竿见影。

4.4 算子融合和编译调优的国产化差异

如果你用的推理引擎支持图编译模式,把多个小算子融合成一个大算子通常能减少内核启动开销和显存中间结果写入。这在国产加速卡上效果更明显,因为很多框架对细碎算子的调度开销比通用生态更敏感。

实操时可以先抓一个典型的解码算子Profile,看看哪个算子耗时占比最高。有一次我们把一个LayerNorm和后面几个逐元素算子融合之后,单Token解码延迟直接降了大概一成。这个收益在长序列场景下会被进一步放大,因为逐Token解码都要执行一遍这些算子。融合是性价比很高的改动,但要注意融合后的数值顺序变化,必须用融合前后的输出做一遍近似比对。

5. 实测中的性能抖动与高并发场景排障

5.1 卡间通信拥塞导致的P99延迟飙升

部署完成后,我们开始压测。最初几个版本的结果很诡异:P50延迟很漂亮,P99却直接翻倍。一开始怀疑是调度抖动,后来逐步排查才发现,瓶颈在卡间通信的All-to-All阶段。

MoE模型在全卡并发跑起来后,所有请求同时触发专家路由,会让卡间通信流量瞬间集中。如果网络拓扑里几条关键链路带宽被占满,后到的通信只能在缓冲区排队,P99自然就恶化了。

解决思路有三个方向:

  • 降低单次通信的Token数量:适当调小推理引擎里的调度切片粒度,让路由请求分批走,避免瞬间冲击。
  • 错峰通信:在框架允许的情况下,给不同优先级的请求设定不同的专家缓存路径。
  • 调整并行策略:如果通信压力实在压不住,就退回到更小的专家并行范围,用显存换通信。

5.2 时延与吞吐之间的平衡口径

在线部署总要在“低延迟”和“高吞吐”之间做取舍。这个地方我们形成了一套自己的压测口径:

  • 记录“输入长度分区”和“输出长度预算”,吞吐统计只算有效业务Token,不把无意义的Padding算进去。
  • P99延迟按分钟级滑动窗口看,不要只看最终压测报告里的一个点。
  • 判断集群是否够用,不是看平均延迟达标,而是看在目标并发下,P99是否还在服务等级协议以内。

如果你发现P99在某个并发值附近突然抬头,基本就是某个资源到瓶颈了。用压测数据往回推,大概率能定位到显存碎片、通信带宽、调度锁三者之一。

5.3 国产推理框架与CUDA习惯的差异

长期在通用计算框架上写代码的同学,拿到国产超节点环境后会有一种处处被束缚的感觉。但这是思维惯性问题,不是平台缺陷。

举个例子。在CUDA生态里,遇到显存不足,大家的习惯是“开一点Swap或者动态申请”;在国产超节点上,显存交换的效率并没有想象中那么高,很多时候反而应该把资源控制前置,减少运行时的动态行为。又比如,很多算子库在通用框架里会自动选择最优实现,但在国产框架里,算子模板可能还停留在早期版本,需要手动指定“高并发小算子”还是“低并发大算子”的实现分支。

遇到性能不符合预期的情况,先去看目标加速卡对应的算子性能和约束说明,不要直接用惯性思维下结论。这一点说起来容易,实际做起来非常难,我们团队至少有两次是在浪费了一轮排查时间之后,才发现是算子实现选择问题。

6. 一套可参考的离线压测与验收流程

6.1 压测脚本设计的几个关键口径

如果要给团队交付一个“能不能上线”的结论,不能只靠一个总吞吐数字。我们最终沉淀下来的压测方案大致包含以下几类:

  • 精度验证:将输入样本固定住,跑一遍离线评估,比较输出和参考答案的匹配度,确认量化/融合没有破坏模型能力。
  • 单卡极限吞吐:压出单卡在目标序列长度下的最大并发和延迟拐点,作为后续扩展的基础。
  • 集群线性度:从单卡开始逐步增加卡数,看吞吐是否线性增长。如果2卡只有单卡1.4倍,就要去排查通信拓扑是不是出了问题。
  • 长稳测试:至少跑数小时,记录显存占用曲线的漂移情况。显存如果持续增长,说明有内存泄漏和分配缓存未释放。

6.2 从压测数据反推超节点配置是否合理

压测的价值不只是“看能跑多少”,而是反过来验证超节点配置选型是否合适。我们有一套简单的判断方法:

  • 如果显存占用率很高,但算力利用率低于一半,说明权重和KV Cache把卡塞满了,实际计算没喂饱。要么考虑更大显存的卡,要么考虑更激进的连续批处理。
  • 如果算力利用率高,但吞吐上不去,多半瓶颈在并发调度和IO路径上。
  • 如果单卡指数不错,多卡线性度差,接下来就专注调网络通信和并行切分,不要再浪费时间去动量化参数。

压测结束之后,我们通常会在报告里单独列一个“配置建议”段落,把每个超节点配置对应的最佳并发区间、最大序列长度约束、量化方案、P99预期都写清楚。有了这套数据,后面每次扩容或换模型,决策成本就低很多。

7. 后续改进方向:把优化经验固化成工具链

目前整个部署和调优流程虽然能跑通,但离“自动化复现”还有一段距离。我们在尝试把模型权重转换、显存预算计算、并行切分配置生成这几步打包成一个配置模板,根据目标超节点参数自动推荐初始配置,跑完压测后再自动修正参数。这样可以避免每次新项目都重复踩沟通、选型、试参数的老路。

另外,国产加速卡的算子迭代速度非常快,每过几个月可能就有新版本算子库、新的编译指令,甚至新的量化指令集。保留好压测基线和历史性能记录就变得很重要。没有基线,新版算子升级之后究竟是变好还是变差,完全靠猜。

如果你们也正在做类似的部署,我的建议是:别一上来就想把全部优化手段都上齐,先把一个最简单的端到端服务跑通,记录下基线数据,再一个一个优化手段叠加,每次叠加都重新压测。这个流程虽然慢,但每一步的收益都看得见,排查问题的时候也清楚是哪个改动引入的。慢就是快。

返回列表