ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

十万卡集群推理优化实战:两周实现三倍吞吐的自建引擎架构解析

十万卡集群推理优化实战:两周实现三倍吞吐的自建引擎架构解析 1. 从标题拆解这次推理基础设施的硬核升级1.1 两周、三倍吞吐、十万卡到底意味着什么先把标题里的三个数字拆开看。两周是迭代周期三倍吞吐是性能结果十万卡是规模量级。这三个词放在一起传递的信息其实非常明确这不是一次实验室里的小修小补而是一次在超大规模生产集群上完成的推理系统重构。做过大模型推理的人都知道单机跑通一个模型和在上万卡集群上稳定服务完全是两码事。单机环境下你调一调 batch size、换个量化方案、开个 KV Cache 优化吞吐翻倍并不稀奇。但到了十万卡这个量级问题会从“模型能不能跑”变成“整个集群的算力利用率能不能维持住”。通信开销、负载均衡、请求调度、显存碎片、故障恢复任何一个环节出问题都会把整体吞吐拖下来。所以“三倍吞吐”这个结果如果是在小集群上拿到的含金量有限但放在十万卡规模上意味着单位算力的产出效率提升了两倍对应的成本下降和容量释放是极其可观的。这也是为什么这个案例值得单独拿出来讲——它触及的是推理基础设施里最难的那部分规模化之后的效率问题。1.2 为什么自建推理基础设施成了必选项很多人会问现在开源推理引擎这么多直接拿来用不就行了为什么要自建这个问题我在实际项目里被问过无数次。答案其实不复杂通用引擎解决的是通用问题而超大规模场景下的瓶颈往往是特定于你的业务形态的。通用推理引擎的设计目标通常是“在合理资源下跑出不错的性能”它要兼顾各种模型结构、各种硬件、各种部署形态。但当你手里握着十万卡、服务的是自家模型的特定请求分布时通用方案里那些为了兼容性做的妥协就会变成实实在在的效率损失。比如调度策略可能不是为你的请求长度分布优化的显存管理可能没有针对你的模型层数做特殊处理并行策略可能没有充分利用你的网络拓扑。自建推理基础设施的核心价值就是把这些“通用妥协”换成“专用优化”。你可以针对自己的模型结构、请求特征、硬件拓扑做端到端的协同设计而不是在一个黑盒外面调参数。这也是为什么头部团队最终都会走向自建这条路——不是开源不好而是规模到了之后每一滴算力都值得被专门优化。1.3 这篇文章适合谁来读如果你只是想在单机上跑个模型做demo那这篇内容对你来说可能偏重了直接用现成的推理框架就够了。但如果你符合下面任何一种情况那接下来的内容应该能给你不少参考正在负责或参与大规模推理集群的建设和优化遇到了推理吞吐上不去、算力利用率低的问题在考虑自建推理引擎还是基于开源方案二次开发对推理系统的调度、并行、显存管理等核心机制感兴趣我会尽量把这次升级背后的思路讲透包括他们可能做了哪些取舍、哪些优化点是真正起作用的、以及在实际操作中容易踩的坑。有些细节是从公开信息里推断的合理实践我会明确标注出来方便你判断哪些可以直接借鉴、哪些需要结合自己的场景调整。2. 推理基础设施的核心设计思路拆解2.1 自建推理引擎的架构选型逻辑要理解这次升级得先搞清楚一个自建推理引擎的架构大概长什么样。和训练框架不同推理系统的核心目标不是“把模型训出来”而是“用最低的成本把请求服务好”。这个目标决定了它的架构重心在几个地方请求调度、显存管理、并行策略、以及和硬件的贴合度。从公开信息来看智谱这套推理基础设施大概率是围绕几个关键模块构建的。最上层是请求接入和调度层负责把进来的请求做批处理、排队、优先级管理。中间是推理执行层管理模型权重的加载、KV Cache 的分配、以及多卡之间的通信。最底下是硬件抽象层处理不同型号加速卡之间的差异。这个分层看起来和通用引擎差不多但关键在于每一层的实现细节。比如调度层通用引擎可能用的是相对固定的批处理策略而自建方案可以根据请求的长度分布做动态调整——短请求和长请求混在一起批处理效率会差很多因为长请求会拖慢整个 batch 的完成时间。自建方案可以做到更细粒度的调度把长度相近的请求聚在一起减少等待浪费。再比如显存管理通用引擎通常用统一的分配策略但自建方案可以针对模型的具体结构做优化。Transformer 类模型的显存占用大头在 KV Cache 和中间激活值上如果能精确控制这两部分的分配和回收就能在同样的显存下塞进更大的 batch直接提升吞吐。2.2 为什么选择在调度和显存上重点突破推理系统的优化点很多但真正能带来数量级提升的往往集中在少数几个地方。从“三倍吞吐”这个结果倒推这次升级的重点大概率落在调度策略和显存管理上而不是单纯靠换硬件或者加机器。先说调度。在十万卡规模下请求的到达是高度动态的不同时段的负载差异可能很大。如果调度策略不够灵活就会出现有的卡忙死、有的卡闲死的情况。自建调度器的优势在于它可以实时感知每张卡的负载状态把新请求优先分配给空闲的卡而不是简单地轮询或者哈希。更进一步它还可以做请求合并——把多个小请求合并成一个 batch 处理减少通信和启动开销。再说显存。KV Cache 是推理显存占用的主要来源之一尤其是在长上下文场景下。通用引擎通常采用预分配或者简单的分页管理但自建方案可以实现更精细的分页注意力机制把 KV Cache 切成固定大小的块按需分配和回收。这样做的好处是显存碎片少利用率高同样的显存能支撑更大的并发。这两个方向的优化理论上都能带来显著的吞吐提升而且它们之间是相互促进的调度做得好batch 更紧凑显存压力就小显存管理做得好能塞进更大的 batch调度的灵活性就更高。这种协同效应是自建方案相比通用引擎的一个重要优势。2.3 并行策略与通信优化的取舍十万卡规模下通信是绕不开的瓶颈。模型并行、数据并行、流水线并行这些策略的选择和组合直接决定了通信开销的大小。通用引擎通常会提供多种并行模式让用户自己选但自建方案可以针对特定模型和硬件拓扑做定制化的并行切分。举个例子如果集群的网络拓扑是分层级的——比如机内互联快、机间互联慢——那并行策略就应该尽量把通信密集的部分放在机内把通信稀疏的部分放到机间。通用引擎可能不会感知这种拓扑差异但自建方案可以。这种优化带来的收益在万卡以上规模会非常明显。另一个关键点是通信与计算的 overlap。理想情况下当一张卡在等待通信结果时它应该同时在计算别的任务而不是干等。自建方案可以通过更细粒度的任务划分和流水线设计把通信时间藏到计算时间后面从而提升整体利用率。这个优化做得好不好往往就是“能用”和“高效”的分界线。3. 核心细节解析与实操要点3.1 请求调度器的关键参数与调优调度器是推理系统的“大脑”它的策略直接决定了资源利用率。在实际操作中有几个参数是必须关注的。第一个是最大 batch size。这个值设得太小算力用不满设得太大显存容易爆而且单个 batch 的完成时间会变长影响延迟。通常的做法是根据显存容量和请求的平均长度来估算一个上限然后在这个上限附近做动态调整。比如显存能塞下 64 个请求那可以把最大 batch size 设成 48 或 56留一些余量应对突发。第二个是请求排队策略。最简单的做法是先进先出但在实际场景里不同请求的优先级和延迟要求是不一样的。自建调度器通常会支持多级队列把高优先级请求放到快速通道低优先级请求放到慢速通道。这样既能保证关键业务的延迟又能利用空闲资源处理后台任务。第三个是批处理窗口。调度器不会每来一个请求就立刻处理而是会等一小段时间攒一批请求一起处理。这个等待时间就是批处理窗口。窗口太短batch 攒不大效率低窗口太长延迟增加。通常这个值在几毫秒到几十毫秒之间需要根据业务对延迟的敏感度来调。实操心得批处理窗口这个参数我建议从 10ms 开始试然后观察两个指标——平均 batch size 和 P99 延迟。如果 batch size 上不去就适当加大窗口如果延迟超标就减小窗口。找到一个平衡点后再根据业务负载的变化做动态调整。3.2 显存管理的分页与回收机制显存管理是推理系统里最“抠细节”的部分。KV Cache 的分配和回收策略直接决定了同样的显存能支撑多大的并发。通用引擎常用的做法是预分配在服务启动时就把 KV Cache 的空间按最大长度预留好。这样做的好处是实现简单但缺点是浪费严重——如果实际请求的平均长度远小于最大长度那大部分预留空间都是闲置的。自建方案更倾向于分页管理。把 KV Cache 切成固定大小的块比如每块存 16 个 token 的 KV然后按需分配。请求来了就分配几块请求结束了就回收。这样做的好处是显存利用率高碎片少。但实现复杂度也更高需要维护一个块分配表还要处理块之间的拼接问题。另一个关键点是显存回收的时机。请求处理完后KV Cache 占用的显存应该尽快回收否则会影响后续请求的分配。但回收太激进也不行因为有些请求可能需要重试或者续写过早回收会导致数据丢失。通常的做法是给每个请求的 KV Cache 加一个引用计数当计数归零时才真正回收。注意分页管理虽然效率高但对实现的要求也高。如果块大小设得不合理比如太小会导致分配表过大管理开销上升太大又会产生内部碎片。一般建议块大小在 16 到 64 个 token 之间具体值要根据模型的最大上下文长度和平均请求长度来定。3.3 并行策略的配置与通信优化并行策略的配置核心是在计算效率和通信开销之间找平衡。常见的并行方式有几种数据并行每张卡持有完整的模型副本处理不同的请求。优点是实现简单缺点是显存占用高因为每张卡都要存一份完整的模型权重。张量并行把模型的每一层切分到多张卡上每张卡只存一部分权重。优点是显存占用低缺点是通信频繁因为每层计算都需要跨卡同步。流水线并行把模型的不同层分配到不同的卡上请求像流水线一样依次经过各层。优点是通信量相对小缺点是容易出现流水线气泡即某些卡在等待上游结果时处于空闲状态。在实际配置中通常会组合使用这几种策略。比如在机内用张量并行因为机内通信快在机间用流水线并行因为机间通信慢。这样可以在保证显存够用的前提下尽量减少跨机通信。通信优化的另一个重点是压缩和量化。在跨卡传输梯度或激活值时可以用低精度格式来减少数据量。比如把 FP32 压缩成 FP16 甚至 INT8通信量能减少一半到四分之三。当然这会对精度有影响需要根据模型对精度的敏感度来决定是否采用。4. 实操过程与核心环节实现4.1 从零搭建推理服务的完整流程假设你现在要从零搭建一套推理服务下面是一个可以参考的流程。这个流程是基于常见实践整理的具体参数需要根据你的硬件和模型来调整。第一步环境准备与依赖安装。先确认硬件型号和驱动版本然后安装对应的推理框架和依赖库。如果是自建引擎通常需要从源码编译这时候要注意编译选项和硬件架构的匹配。比如在 ARM 架构上编译和在 x86 上编译参数是不一样的。第二步模型转换与权重加载。把训练好的模型转换成推理引擎支持的格式。这一步通常包括权重量化、图优化、算子融合等操作。量化是最影响性能的环节之一FP16 通常能带来接近翻倍的吞吐提升而 INT8 还能再提升一些但精度损失也更明显。第三步配置并行策略。根据集群的规模和网络拓扑决定用哪种并行组合。如果是单机多卡张量并行通常就够了如果是多机多卡就需要考虑流水线并行或者混合并行。配置的时候要特别注意卡与卡之间的通信路径尽量让通信密集的操作落在高速链路上。第四步启动服务并压测。先用小规模请求做功能验证确认模型输出正确。然后用压测工具模拟真实负载观察吞吐、延迟、显存占用等指标。压测的时候要从低负载开始逐步增加并发找到系统的拐点——也就是吞吐不再随并发增加而提升的那个点。第五步调优与迭代。根据压测结果调整参数。如果吞吐上不去先看是不是 batch size 太小或者调度窗口太短。如果延迟太高看是不是排队时间太长或者并行策略导致通信开销过大。调优是一个反复迭代的过程通常需要多轮才能找到最优配置。4.2 关键参数的计算与选择过程在调优过程中有几个参数是需要计算的不能拍脑袋定。最大 batch size 的估算。假设你的显存是 80GB模型权重占 40GB那剩下 40GB 可以给 KV Cache 和中间激活值。如果每个请求平均需要 2GB 的 KV Cache那理论上最多能同时处理 20 个请求。但实际中要留一些余量所以最大 batch size 可以设成 16 左右。批处理窗口的计算。假设你的目标是 P99 延迟不超过 200ms而单个 batch 的处理时间是 100ms那批处理窗口最多只能设 100ms。但通常不会设这么大因为还要留时间给排队和调度。一般设成 10ms 到 20ms 比较稳妥。并行度的选择。假设你有 8 张卡模型有 80 层。如果用张量并行每张卡分 10 层那每层计算都需要跨卡通信。如果机内通信延迟是 5 微秒那每层通信开销就是 5 微秒80 层就是 400 微秒。这个开销能不能接受取决于你的单层计算时间。如果单层计算只要 100 微秒那通信开销就太大了这时候可能要考虑用流水线并行来减少通信频率。提示参数计算只是起点实际最优值往往和理论值有偏差。因为理论计算忽略了很多细节比如显存碎片、通信竞争、调度开销等。所以算完之后一定要用压测来验证和微调。4.3 压测与性能验证的实操记录压测是验证优化效果的唯一标准。下面是一个压测流程的参考。先准备压测数据。用真实的请求日志或者模拟的请求分布包括请求长度、到达间隔、并发数等。请求长度分布很重要因为长请求和短请求对系统的影响完全不同。如果只用固定长度的请求压测结果会失真。然后设置压测指标。核心指标有三个吞吐每秒处理的 token 数或请求数、延迟P50、P95、P99、资源利用率GPU 利用率、显存占用、网络带宽。这三个指标要一起看不能只看吞吐。有时候吞吐上去了但延迟也上去了用户体验反而变差。接着是压测执行。从低并发开始比如 10 个并发然后逐步增加到 20、50、100观察指标变化。当吞吐不再随并发增加而提升时说明系统达到了瓶颈。这时候要分析瓶颈在哪里——是显存不够、通信太慢、还是调度器处理不过来。最后是结果分析。如果瓶颈在显存就优化显存管理比如用分页 KV Cache如果瓶颈在通信就调整并行策略减少跨卡通信如果瓶颈在调度就优化调度算法提高批处理效率。5. 常见问题与排查技巧实录5.1 吞吐上不去的典型原因与排查路径吞吐上不去是最常见的问题原因可能有很多。下面是一个排查路径按可能性从高到低排列。第一检查 batch size 是否太小。如果 batch size 只有个位数那算力肯定用不满。先看调度器的配置是不是最大 batch size 设得太保守。如果是适当调大然后观察显存占用和延迟变化。第二检查显存是否成为瓶颈。如果显存占用接近上限那 batch size 就上不去了。这时候要么优化显存管理比如用分页 KV Cache 减少碎片要么用量化降低模型权重的显存占用。第三检查通信是否成为瓶颈。如果 GPU 利用率不高但显存也没满那可能是卡在通信上了。用性能分析工具看一下通信时间占比如果超过 30%就需要优化并行策略。第四检查调度器是否成为瓶颈。如果调度器的处理速度跟不上请求到达速度那请求就会排队吞吐自然上不去。这时候要看调度器的 CPU 占用如果单核跑满了就需要多线程或者分布式调度。第五检查是否有资源竞争。多个进程共享同一张卡时可能会出现资源竞争导致效率下降。确保每个推理进程独占自己的卡不要和其他进程混用。5.2 延迟毛刺的定位与消除延迟毛刺是指 P99 延迟远高于 P50 延迟的情况。比如 P50 是 50ms但 P99 是 500ms那用户体验就会很差。毛刺的常见原因有几个。一是长请求拖尾。如果一个 batch 里混了一个特别长的请求那整个 batch 的完成时间都会被拖长。解决办法是把长请求单独处理或者用连续批处理让短请求先完成先返回。二是显存回收不及时。如果请求处理完后 KV Cache 没有及时回收后续请求就可能因为显存不足而排队。解决办法是优化回收逻辑确保请求结束后立刻释放显存。三是调度抖动。如果调度器在分配请求时出现抖动比如某些卡被分配了过多请求而另一些卡空闲那就会导致部分请求等待时间过长。解决办法是优化负载均衡算法让请求分配更均匀。四是网络抖动。在跨机通信时网络延迟的波动会导致毛刺。解决办法是增加重试机制或者用更稳定的通信协议。实操心得定位毛刺的时候我习惯先看时间序列图。把延迟按时间画出来如果毛刺是周期性的那可能是调度或者回收的问题如果是随机的那可能是网络或者资源竞争的问题。这个判断能帮你快速缩小排查范围。5.3 常见问题速查表问题现象可能原因排查方法解决思路吞吐低GPU 利用率低batch size 太小查看调度器配置和实际 batch size调大最大 batch size优化批处理窗口吞吐低显存占用高显存碎片多查看显存分配日志改用分页 KV Cache优化回收策略延迟高P99 远大于 P50长请求拖尾分析请求长度分布长短请求分开处理用连续批处理延迟高且波动大调度抖动查看各卡负载分布优化负载均衡增加调度频率服务不稳定偶尔超时网络抖动监控网络延迟和丢包增加重试优化通信路径启动慢加载时间长权重加载效率低查看加载日志用并行加载优化权重格式5.4 独家避坑技巧在实际操作中有几个坑是我踩过或者见别人踩过的这里分享出来。第一个坑是过度追求吞吐而忽略延迟。有些人为了把吞吐拉上去把 batch size 设得很大结果延迟飙升用户体验变差。正确的做法是先定延迟目标然后在满足延迟的前提下最大化吞吐。第二个坑是忽略请求长度分布。如果只用固定长度的请求做压测得到的优化参数在真实场景下可能完全不适用。一定要用真实的请求分布来压测或者至少模拟出长短请求混合的场景。第三个坑是并行策略配得太复杂。有些人一上来就用混合并行结果通信开销比计算还大。其实对于大多数场景简单的张量并行或者数据并行就够了。并行策略越复杂调优难度越大出问题的概率也越高。第四个坑是不做灰度发布。推理系统的优化改动一定要先在小流量上验证确认没问题再全量。直接全量上线一旦出问题就是大面积故障。第五个坑是忽略监控。没有监控你就不知道系统在发生什么。吞吐、延迟、显存、GPU 利用率、网络带宽这些指标都要有实时监控和告警。出了问题能第一时间发现而不是等用户投诉。6. 从这次升级看推理基础设施的演进方向6.1 自建与开源的边界在哪里这次升级引出一个值得思考的问题自建和开源的边界到底在哪里我的看法是通用能力用开源差异化能力自建。开源的推理引擎在通用能力上已经做得很好了比如基本的模型加载、批处理、量化支持等。这些能力没有必要重复造轮子。但当你有一些特定的需求时比如特定的调度策略、特定的显存管理方式、特定的并行切分那自建就是必要的。另一个判断标准是规模。在小规模下开源的性能损失可能不明显自建带来的收益不足以覆盖维护成本。但到了十万卡这个量级任何一点效率损失都会被放大自建的收益就非常显著了。6.2 推理效率的下一步突破点在哪里从这次升级来看调度和显存管理的优化空间还很大。下一步的突破点我个人认为可能在几个方向。一是更智能的调度。现在的调度策略大多是基于规则的未来可能会引入学习型调度根据历史请求模式预测未来的负载提前做资源分配。这样能进一步减少等待和空闲。二是更细粒度的并行。现在的并行策略大多是静态的一旦配置好就不变了。未来可能会做动态并行根据请求的特征实时调整并行方式。比如短请求用数据并行长请求用张量并行。三是软硬件协同设计。现在的推理优化大多是在软件层面做的未来可能会和硬件更紧密地结合。比如针对特定加速卡的指令集做算子优化或者利用硬件特性做更高效的通信。6.3 对团队能力的要求变化自建推理基础设施对团队的能力要求也和用开源方案不一样。用开源方案团队只需要会配置和调参就行。但自建方案团队需要具备几个方面的能力。一是系统编程能力。自建引擎涉及到大量的底层操作比如显存管理、通信调度、并发控制这些都需要扎实的系统编程功底。二是性能分析能力。优化推理系统必须会做性能分析。要知道瓶颈在哪里为什么在那里怎么消除。这需要熟练使用各种性能分析工具。三是硬件理解能力。不同的加速卡有不同的特性比如显存带宽、通信延迟、计算单元数量。自建方案需要针对硬件做优化所以团队必须理解硬件的特性。四是快速迭代能力。这次升级只用了两周说明团队的迭代速度非常快。自建方案的一个优势就是可以快速响应需求变化但这要求团队有高效的开发和测试流程。我在实际项目中的体会是自建推理基础设施不是一蹴而就的而是一个持续迭代的过程。第一版可能只比开源方案好一点但随着不断优化差距会逐渐拉大。关键是要有明确的优化目标和持续的投入。另外不要一开始就追求完美先把核心链路跑通然后再逐步优化各个环节。每次优化都做 A/B 测试确认收益后再全量这样风险可控收益也可预期。
返回列表