
作者 | Sean Goedecke
译者 | 王强
策划 | Tina
为何 DeepSeek-V3 在大规模服务场景下表现得又快又省,而在本地运行时却显得缓慢且成本高昂?为何某些 AI 模型刚开始响应迟缓,但一旦启动后速度就大幅提升?
AI 推理服务商常提到一个核心矛盾:吞吐量与延迟之间的权衡。对于任意给定模型,你只能在“高吞吐+高延迟”和“低吞吐+低延迟”之间做选择。实际上,部分模型由于 GPU 利用效率偏低,必须依赖高延迟的服务模式,才能实现可接受的吞吐表现——DeepSeek-V3 正是这类模型的典型代表。
这一权衡的核心在于 推理批处理大小 的设定:服务商并非对单个请求内部进行批处理,而是将数十乃至上百个并发用户的请求合并处理。Transformer 架构的一大特点是,同时计算一批输出几乎与计算单条输出耗时相当。这是怎么做到的?
GPU 擅长执行大规模矩阵乘法(GEMMs)。假设你要将一个 token 输入模型处理(即通过权重矩阵进行变换,忽略其他结构细节)。这个 token 被表示为一个与模型隐藏层维度匹配的向量(1x模型宽度),然后乘以权重矩阵——这就是一次 GEMM 运算。但如果你有十个 token,也可以将它们堆叠成一个 10x 维度的矩阵,一次性完成乘法,仍只算一次 GEMM。相比执行十次小规模 GEMM,这种方式快得多。
因此,推理服务器的工作流程大致如下:
关键点在于:服务器自行决定批处理的规模。这正是吞吐与延迟权衡的来源。如果不批处理,逐个处理 token,用户无需等待(跳过排队步骤),延迟极低(前提是 GPU 资源充足)。但如果采用大批量批处理,用户需等待批次填满,延迟上升,但 GPU 利用率更高,吞吐量显著提升。
为何 GPU 处理大矩阵比多个小矩阵更高效?原因有二:
其一,每次向 GPU 发送指令都有固定开销,一个大矩阵只需一次调用;
其二,每个新任务都需要加载权重,若频繁执行小 GEMM,大量时间将耗费在数据搬运而非计算上。
推理服务器通常设有一个“收集窗口”,请求在此窗口内排队等待。聊天类服务的目标延迟一般为 5–10 毫秒,而高吞吐后端可能容忍高达 200 毫秒的延迟。若请求在窗口开启时到达,它可能要等到窗口关闭才能被处理。当窗口关闭时,所有积压请求被打包成一个批次(多个 1x 向量拼接为单一 128x 矩阵),统一送入模型处理。这种操作周期常被称为一个“tick”。
正如上述机制所示,理论上任何模型都可以在不同批大小下运行。批处理本身不限制模型类型。然而,我们可以设计出 GPU 效率极低的模型,使得不进行大规模批处理就无法达到实用性能。
以专家混合模型(MoE)为例,如 DeepSeek-V3 或传闻中的 GPT-4 所用架构。这类模型可包含数百个“专家”(独立的前馈网络模块),路由机制为每个 token 动态选择激活其中一部分。但这种结构对 GPU 来说效率低下——原因在于:GPU 偏好少量大矩阵运算,而 MoE 强制进行大量小型矩阵乘法。
除非以整批方式处理,否则吞吐量会严重受限。
设想两种收集窗口:5 毫秒 vs 200 毫秒。假设在 5 毫秒内收到 10 个请求。若专家数量众多,某些专家可能仅需处理一两个 token,导致其实际批大小远低于总请求数。这使得每个专家的计算单元利用率极低,无法发挥 GPU 的并行优势。
相比之下,200 毫秒窗口能积累更多请求,使每个专家获得足够多的 token 来维持高效运算。因此,MoE 模型必须牺牲延迟换取吞吐,否则整体效率将急剧下降。
对于层数极多的大型模型,保持 GPU 持续满载是一项挑战。现代大模型往往包含数百个 Transformer 层,必须采用流水线并行(pipeline parallelism):不同 GPU 分别负责不同层段。否则,单卡内存无法容纳全部权重,频繁换入换出将极大拖慢速度。
在推理过程中,每个 token(通常以微批次形式)依次流经各 GPU 层段。
管道效率取决于层数和批处理窗口大小。在一个“tick”中处理一批 token 时,初期后端 GPU 尚无输入(预热阶段),末期前端 GPU 提前空闲(排水阶段)。这些空闲期称为“预热”和“排水”。若窗口太小、tick 过于频繁,则预热与排水时间占比过高,浪费大量算力。
更严重的是,当窗口极短且请求数少于层数时,会出现“管道气泡”——即尚未完成一轮处理,管道已提前进入排水状态。这对吞吐影响巨大。为避免气泡,服务商必须设置足够宽的收集窗口,但这直接带来了更高的延迟。
既然大型服务商拥有海量并发请求,为何不能持续填满队列,彻底消除预热与排水?换句话说,能否抛弃“tick”机制,让 token 微批次像流水一样不间断流动?
理论上可行。每个用户的 token 生成必须顺序进行(前一个未完成不能生成下一个),但服务商整体流量足够大,理应能维持稳定输入流。
问题出在 实际实现 上,尤其是注意力机制的批处理限制:要批量执行注意力 GEMM,所有序列必须具有相同的上下文长度(即历史 token 数相同)。否则,KV 缓存的形状不一致,无法堆叠成统一矩阵。因此,系统只能将相同长度请求分组处理,而不能简单维护一个动态队列。
尽管已有研究尝试解决这一问题(如 https://www.php.cn/link/200734077bb5e01fbe9b973d0d50ee6a tick 处理注意力,而用连续流处理前馈网络(FFN)?
难点在于内存开销:FFN 依赖注意力输出作为输入,若两者异步运行,中间结果需暂存内存,成本极高。现代推理系统倾向于将注意力与 FFN 合并为少数几个大型 GEMM,在同一操作中完成。若拆分到不同 GPU 或阶段执行,则需额外通信和调度开销,反而降低效率。
GPU 在处理大型矩阵乘法时效率最高。将多个 token 堆叠成一个大矩阵进行计算,比逐个处理能获得更高的 token 吞吐量。
在解码阶段,注意力机制要求同批 token 具有相同上下文长度,迫使调度器以“tick”方式运行。每个 tick 中打包的 token 数量即为批大小,这些 token 来自不同用户。你无法对同一用户的不同 token 批处理,因为后续 token 依赖前序输出,因此高效批处理依赖高并发用户流量。
更大的批处理意味着更高延迟——用户可能需等待最多 200 毫秒直到批次填满,但它提升了 FFN 阶段的 GEMM 规模,从而提高整体吞吐。
深层模型(长管道)需要更大的批处理来避免管道气泡,确保每个 tick 的 token 数超过层数。
MoE 模型则需高延迟服务以提升效率:每个专家仅处理分配给它的 token,只有全局批处理足够大,才能让每个专家都有足够任务可做。
推理服务商选择批大小/窗口时,目标是消除管道气泡并让专家模块充分饱和。高批大小带来更高吞吐,但代价是延迟增加。
像 DeepSeek 这样的模型,既是 MoE
以上就是为什么 DeepSeek 大规模部署很便宜,本地很贵的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号