前言
DeepSeek V2的推出,让圈内人都开始关注DeepSeek及其背后的公司——深度求索。再后来,24年12.26日,DeepSeek-V3又出来了,一度在圈内大火
其实本文一开始是属于此文《一文通透DeepSeek V2:通俗理解多头潜在注意力MLA——改造的Transformer多头注意力》的「第四部分 DeepSeek-V3:号称以1/14算力训练出超越Llama 3.1 405B的效果」
但V3实在是太火了,特别是不到一个月后的25年1.20日,DeepSeek R1也出来之后「详见此文《一文速览DeepSeek R1:如何通过纯RL训练大模型的推理能力以比肩甚至超越OpenAI o1(含Kimi K1.5解读)》」,使得2025年春节前后,无论是圈内圈外、还是国内国外,都开始热烈讨论deepseek
- 国内外一些大厂开始反思还要不要大规模招聘那么多人员「deepseek v3的作者/贡献者包括研究与工程、数据标注、业务与合规等方面的人员,全部总计214人,其中研究与工程人员167人」、要不要买那么多张卡
特别是OpenAI、Anthropic、Google、Meta更加紧张,紧张中国AI开始有反超之势,且疑问为何如此低成本,但效果却如此之好 - 且让所有人没有想到的是,25年1.27日,股价曾是世界第一的英伟达股价下跌17%,一下子跌破3万亿,市值被苹果反超
虽说造成英伟达股价下跌的原因有很多,deepseek只是其中一个,但仔细一想,肯定影响不小,毕竟不需要一万多张卡也能训练出超越Llama 3.1 405B的效果,那还买那么多卡干什么呢 - 更何况不但开源(当然了,目前 V3的GitHub上只开源了模型结构和推理脚本,没有开源训练代码,详见本文的第4部分 ),普通用户聊天对话免费,开发者调用API更是便宜好用——API的常规费用上,输入价格为0.5-2元/百万token,输出价格为8元/百万token
相对于GPT-4o 0806版本而言,输入是GPT-4o 0806版本的1/36,输出则是其1/9
所以我司七月推出的一些产品便基于deepseek-v3开发,比如七月在线官网首页的论文chat问答
在阅读本文的过程中
- 首先,如想透彻深入理解V3,建议根据此文 此文《一文通透DeepSeek V2:通俗理解多头潜在注意力MLA——改造的Transformer多头注意力》从头到尾一点一点看
毕竟V3中的很多创新都是源于前期版本的积累——比如DeepSeekMath提出的GRPO、V2版本提出的MLA等等,过程中 我对介绍清楚MLA花了很大的心思、更画了很多手绘图 - 其次,V3中的Multi-Token预测也是借鉴的以前的工作,但原始论文和V3论文对Multi-Token预测的描述都比较晦涩,我花了比较多的时间举例——而且是全网首例
总之,如果各位在其他文章里,没有把GRPO、MLA、Multi-Token预测看的特别明白,或者一目了然,那么恭喜你,你看到了本博客 - 最后,现在网上的信息满天飞,有的文章是否客观也要注意辨别,比如有的帖子称,「“DeepSeek甚至绕过了CUDA”,论文细节再引热议,工程师灵魂提问:英伟达护城河还在吗?」
这就属于夸大了,其实这个问题在v3技术报告中有讲,本文也解读了这点
至于更多,本课程《DeepSeek原理与项目实战营 [从DeepSeek V3、R1到其应用AI Researcher]》里见
很有意思的是,其实deepseek v3技术报告已经把后来引爆全球的R1正式版的4阶段训练过程,透露了一大半——详见下文的3.2节
但在R1爆火之前,又有几个人会把v3报告抠的这么细呢,包括我当时也没看这么细
第一部分 DeepSeek-V3的架构创新:训练GPU和成本均低,但效果卓越
1.1 V3风靡海内外的关键因素:训练成本极低、引领前沿创新
1.1.1 V3训练成本:所用的GPU训练资源仅为Llama 3.1 405B的差不多1/14
24年12月底,深度求索公司再次推出DeepSeek-V2的升级版——DeepSeek-V3,其总参数量达671B,每个token激活37B个参数,其GitHub地址为:github.com/deepseek-ai/DeepSeek-V3
Model | Total Params | Activated Params | Context Length | Download |
---|---|---|---|---|
DeepSeek-V3-Base 属于基础版 | 671B | 37B | 128K | 🤗 Hugging Face |
DeepSeek-V3 属于对话优化版 | 671B | 37B | 128K | 🤗 Hugging Face |
此外,有两点值得关注
- 为了实现高效推理和经济高效的训练,DeepSeek-V3继续采用了多头潜在注意力MLA和DeepSeekMoE架构(毕竟这些架构在DeepSeek-V2中经过了充分验证)
此外,DeepSeek-V3开创了一种无辅助损失的负载平衡策略,并设定了多token预测的训练目标,以实现更强的性能 - 更有意思的是,其参数量虽高达671B,但其所用的GPU训练资源 仅为Llama 3.1 405B的差不多1/14
上面第2点在DeepSeek R1「R1的介绍详见此文《一文速览DeepSeek R1:如何通过纯RL训练大模型的推理能力以比肩甚至超越OpenAI o1(含Kimi K1.5解读)》」出来后,再次被各种媒体疯传——比如称「Meta陷入恐慌?内部爆料:在疯狂分析复制DeepSeek,高预算难以解释」 ,本着严谨求实的角度,我特意验证了下
- 首先,我没有直接找到llama 3.1训练所用的总GPU hour「关于llama 3.1的介绍,详见此文《一文速览Llama 3.1——对其92页paper的全面细致解读:涵盖语言、视觉、语音的架构、原理》」
但网上一搜,很容易搜到这句话:llama 3在 H100-80GB的GPU上累计使用了 3930 万 GPU 小时的计算量
对于这句话的来源,我翻阅了很多资料,大部分资料都是无脑复制,根本看不到最早的出处是哪,直到我找到了Meta官方的Llama 3.3 GitHub——github.com/meta-llama/llama-models/blob/main/models/llama3_3/MODEL_CARD.md:“Training Energy Use Training utilized a cumulative of 39.3M GPU hours of computation on H100-80GB (TDP of 700W) type hardware, per the table below
那llama 3.1呢?在llama 3.1的技术报告第9页中,我找到这句
“Llama 3 405B is trained on up to 16K H100 GPUs”
加之,第13页称,“During a 54-day snapshot period of pre-training, we experienced a total of 466 job interruptions”
这句话 透露两点信息
1 考虑到54天是1296h,故16,384GPU×1,296小时=21,233,664GPU 小时 ≈ 2,123万 GPU 小时
2 因为涉及到各种中断,再加上后续的长上下文扩展、后训练
故最终llama 3.1所用的GPU训练资源和llama 3.3应该是差不多的——即39.3M GPU hours of computation on H100-80GB- 其次,如下表1所总结「Training costs of DeepSeek-V3, assuming the rental price of H800 is $2 per GPU hour,完整训练仅耗费2.788M GPU小时——相当于278.8万 H800 GPU Hours,总训练成本仅为$5.576M——相当于仅 558 万美元,来自DeepSeek-V3技术报告」
在预训练阶段,训练DeepSeek-V3每万亿个tokens仅需180K H800 GPU小时,即在拥有2048个H800 GPU的集群上需要3.7天(llama 3.1用了一万六千张H100,而DS V3只用了2048张H800,这性价比已经很明显的体现出来了)
During the pre-training stage, training DeepSeek-V3 on each trillion tokens requires only 180K H800 GPU hours, i.e., 3.7 days on our cluster with 2048 H800 GPUs.
因此,预训练阶段在不到两个月内完成,耗费2664K GPU小时——即266.4 万 H800 GPU Hours
Consequently, our pre-training stage is completed in less than two months and costs 2664K GPU hours.
再结合用于上下文长度扩展的119K GPU小时和后训练的5K GPU小时,DeepSeek-V3的完整训练仅耗费2.788M GPU小时——相当于278.8万 H800 GPU Hours
Combinedwith 119K GPU hours for the context length extension and 5K GPU hours for post-training,DeepSeek-V3 costs only 2.788M GPU hours for its full training.- 最后,考虑到H100-80G和H800这两者的算力差不多,所以对比小时数的话
Llama 3.3 或Llama 3.1训练:3930 万 H100 GPU 小时
DeepSeek-V3 训练:278.8 万 H800 GPU 小时
后者DeepSeek-V3所需的GPU训练资源是前者Llama 3.3或Llama 3.1的 差不多1/14
而效果对比上呢,在DeepSeek-V3的技术报告中(详见原报告的第15页 table 3),有DeepSeek-V3与Llama 3.1 405B直接PK的数据
即在English、Code、Math、Chinese、Multilingual、Multilingual等五大方面的各种榜单的测试结果上,DeepSeek-V3 略微取胜
你说,用了差不多1/14的成本,然后打败你,你说夸不夸张?^_^
难怪,网上有帖子说Meta内部一些人慌了..
此外,再次强调一下V3的训练成本,如上表格所示
- 假设H800 GPU的租赁价格为每GPU小时$2,完整训练仅耗费2.788M GPU小时——相当于278.8万 H800 GPU Hours,故可以计算出总训练成本仅为$5.576M——相当于仅 558 万美元
这是什么概念呢? - 据Meta内部员工爆料称,Meta内部几十位高管,随便拉出来一位高管 其年薪 都有这个数了..
PS,上述成本仅包括DeepSeek-V3的正式训练,不包括与架构、算法或数据的先前研究和消融实验相关的成本
1.1.2 在国内也能引领世界级前沿
在过去风起云涌的两年,我们见过了很多华人还海外大放异彩(特别是斯坦福在具身领域的前沿研究多半为华人所做),然后国内很多人会follow他们的工作
然反观国内,直接在本土做出影响世界前沿的成就还是屈指可数——而deepseek-V2乃至最新的V3算是其中一例,它告诉我们,在如此前沿的大模型领域,国内本土也是可以做出影响世界前沿的研究的
总之,搞AI、关注AI的这几天讨论deepseek很热烈——不管是V3还是R1
- 中国不缺顶级人才,也不缺大公司,但在AI前沿上,多年来的follow国外,造成了不小的思维定式,结果v3以llama 3.1 400B的1/10成本取得更好效果,让大家意识到国内也可以引领前沿
其实国内一直以来都有引领世界AI前沿的工作,只是影响力没这么大 - 1 把顶级人才 组织好
2 然后做出引领世界前沿
3 的底层创新
4 影响力大
这是4个事情,每个事情难度都不小
但,难度越大 越有意思,也越值得挑战
期待我和我的团队在未来十年也可以做出推动世界前沿的工作
1.2 模型架构:MLA、负载均衡的MoE、Multi-Token预测
1.2.1 多头潜在注意力
为了实现高效推理和经济训练,DeepSeek-V3 继续采用了
- DeepSeek-V2 中已经彻底验证过的 MLA
「注意,本节只是回顾总结下MLA,故对本节所回顾的MLA但凡有任何不明白的地方,请回看此文《一文通透DeepSeek V2:详解MoE、Math版提出的GRPO、V2版提出的MLA(改造Transformer注意力)》的2.2 详解MLA的两个部分:一部分做压缩、一部分做RoPE编码 」 - 和DeepSeekMoE
不过与 DeepSeek-V2 相比,一个例外是作者额外引入了无辅助损失的负载平衡策略——用于DeepSeekMoE以缓解因努力确保负载平衡而导致的性能下降
对于注意力机制,DeepSeek-V3 采用MLA 架构。令 表示嵌入维度,
表示注意力头的数量,
表示每个头的维度,
表示在给定注意力层中第
个token的注意力输入
MLA 的核心是对注意力键和值进行低秩联合压缩,以减少推理期间的键值KV缓存,如下图右下角所示
有
其中
是用于键和值的压缩潜在向量,
表示KV 压缩维度
表示下投影矩阵;
分别是用于键和值的上投影矩阵
是用于生成携带旋转位置嵌入(RoPE)的解耦键的矩阵(Su et al., 2024);RoPE (·) 表示应用RoPE 矩阵的操作;而[·; ·] 表示拼接
注意,对于MLA,上面第一行、第二行的向量——即和
需要在生成过程中缓存,这显著减少了KV 缓存,同时保持了与标准多头注意力MHA相当的性能
且对于注意力查询向量,MLA还执行了低秩压缩,这可以减少训练期间的激活内存,如下图左下角所示:
有
其中,是查询的压缩潜在向量;
表示查询压缩维度;
,
分别是查询的下投影和上投影矩阵;而
是用于生成携带RoPE 的解耦查询的矩阵
最终,注意力查询、键
和值
被组合以产生最终的注意力输出
其中表示输出投影矩阵
1.2.2. 无辅助损失的负载平衡 DeepSeekMoE
对于前馈网络(FFNs),DeepSeek-V3 采用DeepSeekMoE 架构(Dai et al.,2024)。与传统的MoE 架构如GShard(Lepikhin et al., 2021)相比,DeepSeekMoE 使用更细粒度的专家,并将一些专家隔离为共享的
设 表示第
个token的FFN 输入,作者计算FFN 输出
如下
其中
和
分别表示共享专家和路由专家的数量
和
分别表示第
个共享专家和第
个路由专家
表示激活的路由专家的数量;
是第i 个专家的门控值;
是token-expert的亲和度;
是第
个路由专家的中心向量
- 而
表示由计算出的第
个token和所有路由专家的亲和度得分中最高的
个得分组成的集合
不过 与DeepSeek-V2 略有不同,DeepSeek-V3 使用sigmoid 函数来计算亲和度得分,并在所有选定的亲和度得分之间应用归一化以生成门控值
对于MoE 模型,不平衡的专家负载会导致路由崩溃(Shazeer 等,2017)并在专家并行EP场景中降低计算效率
- 传统解决方案通常依赖于辅助损失(Fedus 等,2021;Lepikhin 等,2021)来避免负载不平衡。然而,过大的辅助损失会损害模型性能(Wang 等,2024a)
- 为了在负载平衡和模型性能之间实现更好的权衡,他们首创了一种无辅助损失的负载平衡策略(Wang 等,2024a)以确保负载平衡
具体而言,为每个专家引入一个偏置项,并将其添加到相应的亲和度分数
中以确定前
路由
注意,偏置项仅用于路由。将与FFN 输出相乘的门控值仍然来自原始的亲和度分数。在训练过程中,作者持续监控每个训练步骤的整个批次上的专家负载
在每一步结束时,如果对应的专家超负荷,将偏置项减少,如果对应的专家负载不足,我们将其增加
,其中
是一个称为偏置更新速度的超参数
通过动态调整,DeepSeek-V3 在训练过程中保持了平衡的专家负载,并且比通过纯辅助损失鼓励负载平衡的模型表现更好
此外,尽管DeepSeek-V3主要依赖于无辅助损失策略来实现负载平衡,为了防止任何单个序列内的极端不平衡,他们还采用了互补序列平衡损失
其中平衡因子 是一个超参数,对于DeepSeek-V3 将被赋予一个极小的值;
表示指示函数;
表示序列中的token数量。而序列平衡损失鼓励每个序列上的专家负载达到平衡
此外,他们还做了一下两点措施
- 节点限制路由。与DeepSeek-V2 使用的设备限制路由类似,DeepSeek-V3 也使用了一种受限的路由机制来限制训练期间的通信成本
简而言之,他们确保每个token 最多会被发送到M 个节点,这些节点根据分布在每个节点上的专家的最高亲和度分数之和进行选择
在此约束下,该MoE 训练框架几乎可以实现完全的计算-通信重叠 - 无token丢弃。由于有效的负载均衡策略,DeepSeek-V3在整个训练过程中保持良好的负载均衡。因此,DeepSeek-V3在训练过程中不会丢弃任何token
此外,他们还实施了特定的部署策略以确保推理负载均衡,因此DeepSeek-V3在推理过程中也不会丢弃token
值得一提的,后来deepseek在25年2月下旬的开源周对外开源了Expert Parallelism Load Balancer (EPLB)
1.2.3 多token预测:Multi-Token Prediction——显著加快模型的解码速度
受Gloeckle等人「其对应的论文为《Better & Faster Large Language Models via Multi-token Prediction》,这是由Meta团队发在ICML 2024的一篇Poster」的启发,他们为DeepSeek-V3研究并设置了一个多token预测(MTP)目标,该目标将预测范围扩展到每个位置的多个未来token
一方面,MTP目标可以密集化训练信号并可能提高数据效率。另一方面,MTP可以使模型预先规划其表示,以更好地预测未来token
下图图3展示了他们对MTP的实现——在每个深度对每个token的预测保持完整的因果链
且与上面Gloeckle等人(2024年)使用独立的输出头并行预测 个额外的token不同,DeepSeek-V3依次预测额外的token,并在每次预测深度都保持完整的因果链「which parallelly predicts 𝐷 additional tokens using independent output heads, we sequentially predict additional tokens and keep the complete causal chain ateach prediction depth」
首先,对于MTP 模块
具体来说
- 他们的MTP 实现使用
个顺序模块来预测
个附加的token
第k 个MTP 模块由一个共享的嵌入层、一个共享的输出头
、一个Transformer 块
和一个投影矩阵
组成
- 对于第
个输入token
,在第
个预测深度,首先结合第
个token在第
个深度的表示
,和第
个token的嵌入
,通过线性投影相结合,可得
「For the 𝑖-th input token 𝑡𝑖, at the 𝑘-th prediction depth, we first combine the representation of the 𝑖-th token at the (𝑘−1)-th depth h𝑘−1𝑖∈R𝑑 and the embedding of the (𝑖+ 𝑘)-th token 𝐸𝑚𝑏(𝑡𝑖+𝑘) ∈R𝑑10 with the linear projection」
其中表示连接。特别是,当
时,
指的是由主模型给出的表示。请注意,对于每个MTP模块,其嵌入层都共享源自主模型——its embedding layer is shared with the main model.
组合后的作为第k 层深度的Transformer 块的输入,以产生当前深度的输出表示
其中,T 表示输入序列的长度,表示切片操作(包括左右边界)
- 最后,以
作为输入,共享输出头将计算第k 个附加预测token的概率分布
,其中V 是词汇表大小
输出头OutHead(·)线性映射表示到logits,然后应用Softmax(·)函数计算第k个附加token的预测概率
此外,对于每个MTP模块,其输出头也都共享源自主模型。作者保持预测因果链的原则与EAGLE(Li et al., 2024b)类似,但其主要目标是推测解码(Leviathan et al.,2023; Xia et al., 2023),而作者利用MTP来改进训练
我个人觉得啊,就上面这种表述,包括Gloeckle等人(2024年)原始论文中对Multi-Token Prediction的描述对初学者都不友好,很容易看晕——就快到谁看谁晕乎的程度了,我一开始看 也晕乎了一会,为了更好的理解,我还是给大家举个例子吧「据我所知,截止到25年1.7日之前,下面这个例子在全网也是首例了,过程中还和同事阿荀做了深入的讨论/确认」
比如下图所示,完整序列是t1-t7,当前主模块考虑的输入序列为t1,t2,t3,t4,然后预测t5,t6,t7
由于当
时,
指的是由主模型给出的表示,故有
对于输入token t1,主模型生成表示
对于输入token t2,主模型生成表示
对于输入token t3,主模型生成表示
对于输入token t4,主模型生成表示
- 对于MTP Module 1的预测(注,是如下图第2个模块所示),k = 1
并t2预测t3(或者说,t2辅助
预测t3)
并t3预测t4(或者说,t3辅助
预测t4)
并t4预测t5
并t5预测t6
根据公式21(记住一点,
的下标
永远和主模型的输入下标一致,即
一直等于1 或2 或3 或4)
可以得到各个token的输入表示
将 t1的主模型表示和 t2 的嵌入 Emb(t2)结合,通过公式 21 计算得到
将 t2的主模型表示 和 t3 的嵌入 Emb(t3)结合,通过公式 21 计算得到
将 t3的主模型表示和 t4 的嵌入 Emb(t4)结合,通过公式 21 计算得到
将 t4的主模型表示和 t5 的嵌入 Emb(t5)结合,通过公式 21 计算得到
根据公式22,可得,对于transformer处理
将输入到 Transformer 块 TRM1 中,得到
将输入到 Transformer 块 TRM1 中,得到
将输入到 Transformer 块 TRM1 中,得到
将输入到 Transformer 块 TRM1 中,得到
根据公式23,可得,对于输出头预测
将 输入到输出头 OutHead 中,得到 t3 的预测概率
将 输入到输出头 OutHead 中,得到 t4 的预测概率
将输入到输出头 OutHead 中,得到 t5 的预测概率
将输入到输出头 OutHead 中,得到 t6 的预测概率
- 对于MTP Module 2的预测(注,如下图第3个模块所示),k = 2
并t3预测t4(或者说,t3辅助
预测t4)
并t4预测t5
并t5预测t6
并t6预测t7
输入表示:
将 和 t3 的嵌入 Emb(t3) 结合,通过公式 21 计算得到
将 和 t4 的嵌入 Emb(t4) 结合,通过公式 21 计算得到
将 和 t5 的嵌入 Emb(t5) 结合,通过公式 21 计算得到
将 和 t6 的嵌入 Emb(t6) 结合,通过公式 21 计算得到
Transformer 处理:
将输入到 Transformer 块 TRM2 中,得到
将输入到 Transformer 块 TRM2 中,得到
将输入到 Transformer 块 TRM2 中,得到
将输入到 Transformer 块 TRM2 中,得到
输出头预测:
将 输入到输出头 OutHead 中,得到 t4 的预测概率
将 输入到输出头 OutHead 中,得到 t5 的预测概率
将 输入到输出头 OutHead 中,得到 t6 的预测概率
将 输入到输出头 OutHead 中,得到 t7 的预测概率
其次,对于MTP 训练目标
对于每个预测深度,他们计算一个交叉熵损失 :
其中T 表示输入序列长度,表示第
个位置的真实token,
表示由第k 个MTP 模块给出的
的相应预测概率
最后,他们计算所有深度上的MTP 损失的平均值,并将其乘以一个权重因子,以获得总体MTP 损失
,这作为DeepSeek-V3 的附加训练目标
最后,对于推理中的MTP而言
他们的MTP策略主要旨在提高主模型的性能,因此在推理过程中,可以直接丢弃MTP模块,主模型可以独立正常运行
此外,还可以重新利用这些MTP模块进行推测性解码,以进一步提高生成延迟
遗憾的是,V3官方代码库里 并没有对MTP技术的完整实现
- 如我司大模型同事阿荀所说,MTP只是属于训练期间设定的损失函数和额外结构,官方没有提供训练代码,这里边应该也意味着不提供MTP的实现
- meta 虽然有个mtp实现,但本节开头已经说了:ds的mtp实现和meta的mtp实现 有点区别
那咋办呢,请看此文《MLA实现及其推理上的十倍提速——逐行解读DeepSeek V2中多头潜在注意力MLA的源码(图、公式、代码逐一对应)》
第二部分 DeepSeek-V3基础设施层面的创新:FP8 训练等
DeepSeek-V3在配备了2048块NVIDIA H800 GPU的集群上进行训练。H800集群中的每个节点包含8块通过NVLink和NVSwitch连接的GPU。在不同的节点之间,使用InfiniBand(IB)互连以促进通信
2.1 训练框架(含GPU的内部结构示意图)
DeepSeek-V3 的训练由 HAI-LLM 框架支持,这是一个由他们的工程师从头打造的高效且轻量级的训练框架
总体而言,DeepSeek-V3 应用了 16 路流水线并行(PP)(Qi等,2023a)、64 路专家并行Expert Parallelism(Lepikhin 等,2021)跨越 8 个节点,以及ZeRO-1 数据并行DP「关于ZeRO-1 数据并行DP,详见此文《大模型并行训练指南:通俗理解Megatron-DeepSpeed之模型并行与数据并行(含ZeRO优化)》第4部分的介绍:第四部分 数据并行与ZeRO」
为了促进DeepSeek-V3的高效训练,他们实施了精细的工程优化
- 首先,设计了DualPipe算法以实现高效的流水线并行
与现有的PP方法相比,DualPipe具有更少的流水线气泡。更重要的是,它在前向和后向过程中重叠了计算和通信阶段,从而解决了跨节点专家并行引入的沉重通信开销的挑战
有意思的是,后来deepseek在25年2月下旬的开源周中,对外开源了DualPipe、DeepEP(专家并行通信库) - 其次,开发了高效的跨节点全互通信内核,以充分利用IB和NVLink带宽,并节省专用于通信的流式多处理器SMs
- 最后,精心优化了训练期间的内存占用,从而使得能够在不使用昂贵的张量并行(TP)的情况下训练DeepSeek-V3
补充一下GPU的内部结构,如下图所示(这是图源)
- 寄存器
这些寄存器是每个线程专用的,这意味着分配给一个线程的寄存器对其他线程不可见。编译器会决定寄存器的使用情况- L1/共享内存 (SMEM)
每个 SM 都有一个快速的片上暂存器内存,可用作 L1 缓存和共享内存。CUDA 块中的所有线程都可以共享共享内存,并且给定 SM 上运行的所有 CUDA 块都可以共享 SM 提供的物理内存资源
总之,L1 缓存是小型、快速且专用的缓存,是每个流多处理器的本地缓存- 只读存储器
每个 SM 都有一个指令缓存、常量存储器、纹理存储器和 RO 缓存,对于内核代码来说是只读的- L2 缓存
L2 缓存在所有 SM 之间共享,因此每个 CUDA 块中的每个线程都可以访问此内存。NVIDIA A100 GPU将 L2 缓存大小增加到 40 MB,而 V100 GPU 中为 6 MB- 全局内存
这是 GPU 的帧缓冲区大小以及位于 GPU 中的 DRAM
全局内存是一个逻辑内存空间,其物理后备是L1 缓存、L2 缓存和设备内存Device Memory
- 当内核从全局内存读取数据时,实际数据可以从这三个物理内存空间中的任何一个中检索,当线程从全局内存请求数据时
首先检查 L1 缓存
如果在 L1 缓存中未找到数据,则向 L2 缓存发出读取请求——这称为L2 缓存未命中
同样,如果数据不在 L2 缓存中,则向设备内存发出读取请求——即设备内存缓存未命中- CUDA 内核线程从全局内存中以 32 字节块(称为“扇区”)读取数据,如下图所示——这是图源
2.1.1 双管道DualPipe与计算-通信重叠(后已对外开源)
对于DeepSeek-V3,由跨节点专家并行引入的通信开销导致计算与通信的比率约为1:1,效率低下
为了解决这一挑战,他们设计了一种创新的流水线并行算法,称为双管道(DualPipe),它不仅通过有效重叠前向和反向计算-通信阶段加速模型训练,还减少了流水线气泡「which not only accelerates model training by effectively overlapping forward and backward computation-communication phases, but also reduces the pipeline bubbles」
DualPipe的关键思想是在一对单独的前向和反向块中重叠计算和通信——即overlap the computation and communication with in a pair of individual forward and backward chunks。具体来说,将每个块分为四个组件:注意力、全对全分发、MLP、全对全合并
- 特别地
对于一个后向块,注意力和MLP都进一步分为两部分,输入的后向和权重的后向,类似于ZeroBubble(Qi等,2023b) - 此外,还有一个PP通信组件
如图4所示
“ 这是一对单独的前向和后向块的重叠策略(transformer块的边界未对齐)
橙色表示前向 △ —— 在下图第一行左侧区块的右边
蓝色表示“权重的后向” ▲ —— 在下图第一行左侧区块的中间
绿色表示“输入的后向” ▲ —— 在下图第一行左侧区块的左边
紫色表示PP通信,红色表示障碍
全互通信和PP通信都可以完全隐藏(Both all-to-all and PP communication can be fully hidden) ”
对于一对前向和后向块,重新排列这些组件并手动调整分配给通信与计算的GPU SMs的比例
As illustrated in Figure 4, for a pair of forward and backward chunks, we rearrange these components and manually adjust the ratio of GPU SMs dedicated to communication versus computation.
在这种重叠策略中,可以确保在执行过程中全对全和PP通信都可以完全隐藏
In this overlapping strategy, we can en sure that both all-to-all and PP communication can be fully hidden during execution - 鉴于这种高效的重叠策略,完整的DualPipe调度如图5所示「8 个 PP 级和 20 个微批次在两个方向上的 DualPipe 调度示例。 反向方向的微批次与正向方向对称,为了简单说明,省略了它们的批次 ID。由共享黑边框包围的两个单元格具有相互重叠的计算和通信」
且如上所说
橙色表示前向
绿色表示“输入的后向”
蓝色表示“权重的后向”
它采用双向流水线调度,同时从流水线的两端同时输入微批次,并且大部分通信可以完全重叠。这种重叠还确保了随着模型的进一步扩展,只要保持恒定的计算与通信比率,仍然可以在节点之间使用细粒度的专家,同时实现接近零的全对全通信开销
此外,即使在没有沉重通信负担的更一般场景中,DualPipe 仍然表现出效率优势
在下表表2 中「不同流水线并行方法的流水线气泡和内存使用情况比较。表示前向块的执行时间,
表示完整反向块的执行时间,
表示“权重反向”块的执行时间,
&
表示两个相互重叠的前向和反向块的执行时间」
总结了不同PP 方法中的流水线气泡和内存使用情况。如表所示
- 与ZB1P (Qi et al., 2023b) 和1F1B (Harlapet al., 2018) 相比,DualPipe 显著减少了流水线气泡,而峰值激活内存仅增加了1P P 倍
虽然DualPipe需要保留两份模型参数,但由于在训练期间使用了较大的EP 大小,这并不会显著增加内存消耗 - 与Chimera (Li and Hoefler, 2021) 相比,DualPipe 只要求流水线阶段和微批次可被2 整除,而不要求微批次可被流水线阶段整除
此外,对于DualPipe,随着微批次数量的增加,气泡和激活内存都不会增加
2.1.2 跨节点全对全通信的高效实现:通过PXT连接CUDA和底层GPU硬件
为了确保DualPipe 具有足够的计算性能,他们定制了高效的跨节点全互通信内核(包括分发和组合),以节省专用于通信的SM 数量。内核的实现与MoE 门控算法和他们集群的网络拓扑共同设计
- 具体来说,在他们的集群中,跨节点GPU 通过IB 完全互联,节点内通信通过NVLink 处理。NVLink 提供160 GB/s 的带宽,大约是IB(50 GB/s)的3.2 倍
- 为了有效利用IB 和NVLink 的不同带宽,他们限制每个token 最多被分发到4 个节点,从而减少IB 流量
对于每个token,当其路由决定被做出后,它将首先通过IB 传输到目标节点上具有相同节点内索引的GPU。一旦到达目标节点,他们将努力确保它通过NVLink 即时转发到特定的GPU 上,这些GPU 托管着它们的目标专家,而不被随后到达的token阻塞
通过这种方式,IB 和NVLink 的通信完全重叠,每个token 可以在不产生NVLink 额外开销的情况下高效选择每个节点平均3.2 个专家
这意味着,尽管DeepSeek-V3在实践中仅选择8个路由专家,它可以将这个数量扩展到最多13个专家 (4个节点×3.2个专家/节点),同时保持相同的通信成本
总体而言,在 这样的通信策略下,仅需20个SM即可充分利用IB和NVLink的带宽
具体来说,deepseek V3采用了扭曲专用技术warp specialization technique 「Bauer et al., 2014——Singe: Leveraging Warp Specialization for High Performance on GPUs,关于warp,每个流多处理器都有一个或多个Warp 调度器,负责选择在 SM 计算核心上执行哪些 Warp,且此文里也有对应的介绍:PyTorch CUDA入门」并将20个SM划分为10个通信通道,即we employ the warp specialization technique (Bauer et al., 2014) and partition20 SMs into 10 communication channels
- 在调度过程中
1)IB发送
2)IB到NVLink转发
以及3)NVLink接收由各自的扭曲处理
根据所有SM的实际工作负载,动态调整分配给每个通信任务的扭曲数量
During the dispatching process, (1) IB sending, (2)IB-to-NVLink forwarding, and (3) NVLink receiving are handled by respective warps. Thenumber of warps allocated to each communication task is dynamically adjusted according to theactual workload across all SMs. - 同样,在合并过程中
1)NVLink发送
2)NVLink到IB转发和累积
以及(3)IB接收和累积也由动态调整的扭曲处理
Similarly, during the combining process, (1) NVLink sending,(2) NVLink-to-IB forwarding and accumulation, and (3) IB receiving and accumulation are alsohandled by dynamically adjusted warps.
此外,调度和合并内核与计算流重叠,因此他们也考虑了它们对其他SM计算内核的影响——In addition, both dispatching and combining kernelsoverlap with the computation stream, so we also consider their impact on other SM computationkernels.
具体来说,他们使用定制的PTX(并行线程执行)指令并自动调整通信块大小,这显著减少了L2缓存的使用和对其他SM的干扰
Specifically, we employ customized PTX (Parallel Thread Execution) instructions andauto-tune the communication chunk size, which significantly reduces the use of the L2 cache and the interference to other SMs
非常值得一提的是,如此文所说,PTX在接近汇编语言的层级运行,基于 SIMT(单指令多线程)模型,支持大规模并行计算,且允许进行细粒度的优化「说白了,就是可以更好的优化性能,提升GPU运行效率」,如寄存器分配和Thread/Warp级别的调整——即直接操作线程(thread)、线程块(block)和网格(grid)级别的数据
- 换言之,PTX位于高级GPU编程语言(如CUDA C/C++)和低级机器代码(如流式汇编或SASS)之间,充当着高级语言CUDA和底层硬件之间的桥梁
关于CUDA,上面提到的这篇文章确实非常值得一看:PyTorch CUDA入门- 也就是说,在实际编译流程中,CUDA代码首先被编译为PTX代码,PTX代码再被编译为目标GPU架构的机器码(SASS,Streaming ASSembler)
比如如下代码所示,高级 CUDA 代码(.cu
)通过nvcc
编译器生成 PTX 代码(.ptx
),再由驱动程序动态编译为目标 GPU 的 SASS 机器码nvcc --ptx code.cu # 生成 PTX 文件
- PTX 语法类似汇编,但更结构化,如下图所示
2.1.3. 极致内存节省与最小开销
为了在训练过程中减少内存占用,采用了以下技术
- 重新计算RMSNorm和MLA上投影
他们在反向传播过程中重新计算所有RMSNorm操作和MLA上投影,从而无需持久存储其输出激活。尽管有些许开销,这一策略显著减少了存储激活所需的内存 - CPU中的指数移动平均
在训练过程中,他们保留模型参数的指数移动平均(EMA),以便在学习率衰减后对模型性能进行早期估计。EMA参数存储在CPU内存中,并在每次训练步骤后异步更新。此方法使他们能够在不增加额外内存或时间开销的情况下维护EMA参数 - 共享嵌入和输出头用于多token预测
如下图中标绿的embedding layer和output head
通过使用DualPipe策略,他们在同一PP等级上部署模型中最浅的层(包括嵌入层)和最深的层(包括输出头)
这种安排使得共享嵌入和输出头的参数和梯度在MTP模块和主模型之间实现物理共享。这种物理共享机制进一步增强了他们的内存效率
2.2 FP8训练:虽算的快 但精度不够,故需提高精度
受到最近低精度训练进展的启发(Dettmers等,2022;Noune等,2022;Peng等,2023b),他们提出了一种利用FP8数据格式进行DeepSeek-V3训练的细粒度混合精度框架
- 虽然低精度训练具有很大的潜力,但通常受到激活、权重和梯度中的异常值的限制(Fishman等,2024;He等;Sun等,2024)
总之,尽管在推理量化方面已取得显著进展(Frantar 等人,2022 年;Xiao 等人,2023 年),但在大规模语言模型预训练中成功应用低精度技术的研究相对较少(Fishman 等人,2024 年) - 为了解决这一挑战并有效扩展FP8 格式的动态范围,作者引入了一种细粒度量化策略:具有1 × Nc 元素的平铺分组或具有Nc × Nc 元素的块状分组。在他们增加精度的累加过程中,相关的反量化开销大大减少,这是实现准确FP8 通用矩阵乘GEMM的关键
此外,为了进一步减少MoE 训练中的内存和通信开销,他们在FP8 中缓存和分派激活,同时以BF16 存储低精度优化器状态。他们在两个与DeepSeek-V2-Lite 和DeepSeek-V2 相似的模型规模上验证了所提出的FP8 混合精度框架,训练约1 万亿个tokens(更多细节见附录B.1)
值得注意的是,与BF16 基线相比,他们的FP8 训练模型的相对损失误差始终保持在0.25 % 以下,这一水平完全在训练随机性的可接受范围内
后来,deepseek对外开源了通用矩阵乘法加速库:DeepGEMM,采用了V3中提出的细粒度scaling技术,仅用300行代码就实现了简洁高效的FP8通用矩阵乘法
2.2.1 混合精度框架
基于广泛采用的低精度训练技术(Kalamkar等,2019;Narang等,2017),他们提出了一种用于FP8训练的混合精度框架
在这个框架中,大多数计算密集型操作在FP8中进行——效率高 但精度不够,而一些关键操作则策略性地保持其原始数据格式——效率低 但精度够,以平衡训练效率和数值稳定性
整体框架如图6所示
- 首先,如上图所示,为了加速模型训练,大多数核心计算内核,即GEMM操作,都是以FP8精度实现的。这些GEMM操作接受FP8张量作为输入,并生成BF16或FP32格式的输出
如图6所示,与线性算子相关的所有三个GEMM,即Fprop(前向传递)、Dgrad(激活反向传递)和Wgrad(权重反向传递),都在FP8中执行
该设计理论上使计算速度比原始BF16方法提高了一倍。此外,FP8 Wgrad GEMM允许激活在反向传递中以FP8格式存储。这显著减少了内存消耗 - 尽管FP8格式在效率上具有优势,某些算子由于对低精度计算的敏感性,仍然需要更高的精度
此外,一些低成本的算子也可以在几乎不增加总体训练成本的情况下利用更高的精度
因此,经过仔细研究,他们对以下组件保持原始精度(例如,BF16或FP32):
嵌入模块、输出头、MoE门控模块、归一化算子和注意力算子
这些针对性的高精度保留确保了DeepSeek-V3的稳定训练动态
为了进一步保证数值稳定性,他们以更高的精度存储主权重、权重梯度和优化器状态
这些高精度组件会带来一些内存开销,但通过在我们的分布式训练系统中跨多个DP等级进行高效分片,可以将其影响降到最低
2.2.2. 通过量化和乘法提高精度
基于他们的混合精度FP8框架,他们引入了几种策略来提高低精度训练的准确性,重点关注量化方法和乘法过程
- 细粒度量化
在低精度训练框架中,由于FP8 格式的动态范围受限于其减少的指数位,溢出和下溢是常见的挑战
作为标准做法,输入分布通过将输入张量的最大绝对值缩放到FP8 的最大可表示值来对齐FP8 格式的可表示范围(Narang et al., 2017)「As a standard practice, the input distribution is aligned to therepresentable range of the FP8 format by scaling the maximum absolute value of the inputtensor to the maximum representable value of FP8 (Narang et al., 2017)」。这种方法使得低精度训练对激活异常值非常敏感,这可能严重降低量化精度
为了解决这个问题,他们提出了一种细粒度量化方法,在更细的层次上应用缩放。如图7(a)所示
(1)对于激活,他们在1x128 的瓦片基础上分组并缩放元素(即,每个token 每128个通道);——1) for activations, we group and scale elements on a 1x128 tile basis (i.e., per token per 128 channels);
(2)对于权重,他们在128x128 的块基础上分组并缩放元素(即,每128 个输入通道 每128个输出通道)。这种方法通过根据较小的元素组调整缩放比例,确保量化过程能够更好地适应异常值——and (2) for weights, wegroup and scale elements on a 128x128 block basis (i.e., per 128 input channels per 128 out put channels).
在附录B.2 中,他们进一步讨论了当他们在块基础上分组和缩放激活时,与权重量化相同的方式时的训练不稳定性
他们方法的一个关键修改是在GEMM操作的内维度引入了每组缩放因子。此功能在标准FP8 GEMM中并不直接支持。然而,结合他们精确的FP32累加策略,它可以能够高效实现
值得注意的是,他们的细粒度量化策略与微缩格式的理念高度一致(Rouhani等,2023b),而NVIDIA下一代GPU(Blackwell系列)的Tensor Cores已宣布支持具有更小量化粒度的微缩格式(NVIDIA,2024a) - 增加累积精度Increasing Accumulation Precision
低精度GEMM 操作通常会遇到下溢问题,其准确性很大程度上依赖于高精度累积,通常在FP32 精度下进行(Kalamkar et al., 2019; Narang et al., 2017)
然而,他们观察到在NVIDIA H800GPU 上,FP8 GEMM 的累积精度仅能保留大约14 位,这显著低于FP32 的累积精度。当内维度K 较大时,这个问题会更加突出(Wortsman et al., 2023),这在大规模模型训练中是一个典型场景——其中批量大小和模型宽度都在增加
以两个随机矩阵的GEMM 操作为例,当K = 4096 时,在他们的初步测试中,Tensor Cores 的有限累积精度导致最大相对误差接近2 %。尽管存在这些问题,有限的累积精度仍然是一些FP8 框架中的默认选项(NVIDIA, 2024b),严重限制了训练精度——说白了,就是FP8的精度不够
为了解决这个问题,他们采用了提升到CUDA Cores 以获得更高精度的策略(Thakkar 等,2023)。该过程如图7(b)所示
具体来说,为了提高累积精度,在Tensor Cores 上执行MMA(矩阵乘法累加)时,中间结果使用有限的位宽进行累加。一旦达到NC 的间隔,这些部分结果将被复制到CUDA Cores 上的FP32 寄存器中,在那里进行全精度的FP32 累加
如前所述,他们的细粒度量化沿内维度K 应用每组缩放因子。这些缩放因子可以在CUDA Cores 上高效地进行乘法运算,作为去量化过程,几乎不增加额外的计算成本
值得注意的是,此修改减少了单个warpgroup 的WGMMA(Warpgroup-level Matrix Multiply-Accumulate)指令发出率。然而,在H800 架构上,通常两个WGMMA 可以同时进行:当一个warp-group 执行提升操作时,另一个可以执行MMA 操作
该设计使得两种操作可以重叠,从而保持TensorCores 的高利用率。根据我们的实验,设置NC = 128 个元素,相当于4 个WGMMA,代表了能够显著提高精度而不引入大量开销的最小累积间隔 - 尾数优于指数
与之前的工作(NVIDIA, 2024b; Peng et al., 2023b; Sun et al.,2019b)采用的混合FP8格式不同,该格式在Fprop中使用E4M3(4位指数和3位尾数),在Dgrad和Wgrad中使用E5M2(5位指数和2位尾数),他们在所有张量上采用E4M3格式以获得更高的精度
他们将这种方法的可行性归因于我们的细粒度量化策略,即平铺和块状缩放。通过对较小的元素组进行操作,他们的方法有效地在这些分组元素之间共享指数位,缓解了动态范围有限的影响 - 在线量化
延迟量化用于张量级量化框架中(NVIDIA, 2024b; Peng et al., 2023b),其保留了最大绝对值的历史记录
通过前几次迭代的值来推断当前值。为了确保准确的比例并简化框架,他们在线计算每个1x128激活块或128x128权重块的最大绝对值
基于此,他们推导出缩放因子,然后在线将激活或权重量化为FP8格式
2.2.2 低精度存储和通信:降低内存和通信开销
结合他们的FP8训练框架,通过将缓存的激活和优化器状态压缩为低精度格式,进一步减少内存消耗和通信开销
- 低精度优化器状态
采用BF16数据格式而非FP32来跟踪AdamW(Loshchilov和Hutter,2017)优化器中的一阶和二阶矩,而不会造成明显的性能下降
然而,主权重(由优化器存储)和梯度(用于批量大小累积)仍然保留在FP32中,以确保整个训练过程中的数值稳定性 - 低精度激活
如图6所示:“与线性算子相关的所有三个GEMM,即Fprop(前向传递)、Dgrad(激活反向传递)和Wgrad(权重反向传递),都在FP8中执行”
而其中权重反向传递的Wgrad操作是在FP8中执行的
为了减少内存消耗,自然选择在FP8格式中缓存激活,以用于Linear算子的反向传播。然而,针对几个算子进行了特殊考虑,以实现低成本的高精度训练
1) 线性层的输入在注意力操作符之后。这些激活也在注意力操作符的反向传播中使用,这使得它对精度很敏感
作者采用专门定制的E5M6数据格式专用于这些激活。此外,这些激活将在反向传播中从1x128量化块转换为128x1块。为了避免引入额外的量化误差,所有的缩放因子都是整倍数缩放,即2的整数次幂
2) MoE中SwiGLU算子的输入。为了进一步降低内存成本,他们缓存SwiGLU算子的输入,并在反向传播中重新计算其输出。这些激活也通过我们的细粒度量化方法存储在FP8中,达到了内存效率与计算准确性之间的平衡 - 低精度通信
通信带宽是训练MoE模型的一个关键瓶颈
为了解决这个问题,作者在MoE上投影之前将激活量化为FP8,然后应用分派组件,这与MoE上投影中的FP8 Fprop兼容。就像注意力操作符之后的线性输入一样,这种激活的缩放因子是2的整数幂。类似的策略也应用于MoE下投影之前的激活梯度。对于正向和反向组合组件,我们将它们保留在BF16中,以在训练流水线的关键部分保持训练精度
2.3 推理与部署
他们将将 DeepSeek-V3 部署在 H800 集群上,其中每个节点内的 GPU 通过 NVLink 互连,整个集群内的所有 GPU 通过 IB 完全互连
且为了同时确保在线服务的服务级别目标(SLO)和高吞吐量,他们采用以下部署策略,将预填充阶段和解码阶段分开
2.3.1 预填充
首先,预填充阶段的最小部署单元由4个节点和32个GPU组成
- attention部分采用4路张量并行(TP4)结合序列并行(SP),并结合8路数据并行(DP8)。其小规模的4路TP限制了TP通信的开销
+----------------+ +----------------+ | Node 1 | | Node 2 | | TP0 | | TP1 | | +----+ +----+| | +----+ +----+| | |GPU1| |GPU2|| | |GPU1| |GPU2|| | +----+ +----+| | +----+ +----+| | ... || | ... || | +----+ +----+| | +----+ +----+| | |GPU8| |GPU8|| | |GPU8| |GPU8|| +----------------+ +----------------+
+----------------+ +----------------+ | Node 3 | | Node 4 | | TP2 | | TP3 | | +----+ +----+| | +----+ +----+| | |GPU1| |GPU2|| | |GPU1| |GPU2|| | +----+ +----+| | +----+ +----+| | ... || | ... || | +----+ +----+| | +----+ +----+| | |GPU8| |GPU8|| | |GPU8| |GPU8|| +----------------+ +----------------+
- 对于MoE部分,他们使用32路专家并行(EP32),确保每个专家处理足够大的批量,从而提高计算效率
+----------------+ +----------------+ | Node 1 | | Node 2 | | EP0-EP7 | | EP8-EP15 | | +----+ +----+| | +----+ +----+| | |GPU1| |GPU2|| | |GPU1| |GPU2|| | +----+ +----+| | +----+ +----+| | ... || | ... || | +----+ +----+| | +----+ +----+| | |GPU8| |GPU8|| | |GPU8| |GPU8|| +----------------+ +----------------+
+----------------+ +----------------+ | Node 3 | | Node 4 | | EP16-EP23 | | EP24-EP31 | | +----+ +----+| | +----+ +----+| | |GPU1| |GPU2|| | |GPU1| |GPU2|| | +----+ +----+| | +----+ +----+| | ... || | ... || | +----+ +----+| | +----+ +----+| | |GPU8| |GPU8|| | |GPU8| |GPU8|| +----------------+ +----------------+
- 对于MoE的全对全通信,使用与训练相同的方法:首先通过IB在节点间传输token,然后通过NVLink在节点内的GPU之间进行转发
特别是,他们在浅层的密集MLP中使用1路张量并行,以节省TP通信
其次,为了在MoE部分实现不同专家之间的负载平衡,需要确保每个GPU处理的token数量大致相同。为此,我们引入了一种冗余专家的部署策略,该策略复制高负载专家并冗余部署它们
- 高负载专家是根据在线部署期间收集的统计数据检测到的,并定期调整(例如,每10分钟)。在确定冗余专家集合后,他们根据观察到的负载在节点内的小心重新安排GPU之间的专家,努力在不增加跨节点全互联通信开销的情况下尽可能平衡GPU之间的负载
- 在DeepSeek-V3的部署中,他们为预填充阶段设置了32个冗余专家。对于每个GPU,除了其原本托管的8个专家之外,还将托管一个额外的冗余专家
此外,在预填充阶段,为了提高吞吐量并隐藏全连接和 TP 通信的开销,他们同时处理两个具有相似计算工作负载的微批次,将一个微批次的注意力和 MoE 与另一个微批次的调度和合并重叠
+----------------+ +----------------+
| Microbatch 1 | | Microbatch 2 |
| Attention | | Forward |
| MoE | | Backward |
| ... | | ... |
+----------------+ +----------------+
最后,我们正在探索一种针对专家的动态冗余策略,其中每个GPU容纳更多的专家(例如,16个专家),但在每个推理步骤中只激活9个。在每层开始全互操作之前,动态计算全局最优路由方案。鉴于预填阶段涉及的大量计算,计算此路由方案的开销几乎可以忽略不计
2.3.2 解码
// 待更
2.4 硬件设计建议
// 待更
第三部分 DeepSeek-V3的预训练与后训练
3.1 预训练
3.1.1 数据构建:提高数学、编程、多语言样本,最终14.8T语料
首先,与DeepSeek-V2相比
- 他们通过提高数学和编程样本的比例来优化预训练语料,同时扩展了多语言覆盖范围,不仅限于英语和中文
- 此外,他们的数据处理流程进行了改进,以在保持语料多样性的同时最大限度地减少冗余。受Ding等人(2024)的启发,实施了文档打包方法以确保数据完整性,但在训练过程中未采用跨样本注意力掩码「Inspired by Ding et al. (2024), we implement the documentpacking method for data integrity but do not incorporate cross-sample attention masking during training」
- 最终,DeepSeek-V3的训练语料由他们的tokenizer中的14.8T高质量且多样化的token组成
其次,在DeepSeekCoder-V2(DeepSeek-AI,2024a)的训练过程中,他们观察到填充中间(FIM)策略在不影响下一个词预测能力的同时,使模型能够根据上下文线索准确预测中间文本
- 故为了与DeepSeekCoder-V2保持一致,在DeepSeek-V3的预训练中引入了FIM策略
- 具体而言,采用前缀-后缀-中间(PSM)框架来构建数据,如下所示:
这种结构在文档级别作为预打包过程的一部分进行应用。FIM策略以0.1的比率应用,与PSM框架一致
最后,DeepSeek-V3的分词器采用字节级Byte-level BPE(Shibata等,1999),并扩展了128K词汇表。且他们的分词器的预分词器和训练数据经过修改,以优化多语言压缩效率
- 与DeepSeek-V2相比,新的预分词器引入了结合标点符号和换行符的词元。然而,这一技巧在模型处理没有终止换行符的多行提示时,尤其是在少样本评估提示中,可能会引入词元边界偏差(Lundberg,2023)
- 为了解决这个问题,他们在训练过程中随机拆分一定比例的这种组合词元,使模型接触到更多特殊情况,从而减轻这种偏差
3.1.2 超参数
对于模型超参数
他们将Transformer 层数设置为61,隐藏维度设置为7168。所有可学习参数均随机初始化,标准差为0.006
在MLA 中 「再次强调一下,如果想直观形象的了解下面各种维度,包括各自的对比,请详看此文《一文通透DeepSeek V2:通俗理解多头潜在注意力MLA——改造的Transformer多头注意力》,比如2.2.1 MLA对Q K V的压缩:先对KV联合压缩后升维,再对Q压缩后升维」,他们将
- 注意力头数
设置为128
- 每个头的维度
设置为128
- KV压缩维度
设置为512——同deepseek v2:
被设置为
- 查询压缩维度
设置为1536
- 对于解耦查询和键,将每个头的维度
设置为64——同deepseek v2:
被设置为
- 将除前三层外的所有FFN 替换为MoE 层。每个MoE 层由1 个共享专家和256 个路由专家组成,其中每个专家的中间隐藏维度为2048。在路由专家中,每个token 将激活8 个专家,并确保每个token 最多被发送到4 个节点
- 多token 预测深度D 设置为1,即除了确切的下一个token 外,每个token 将预测一个额外的token
- 与DeepSeek-V2 一样,DeepSeek-V3 在压缩的潜在向量之后也采用了额外的RMSNorm 层,并在宽度瓶颈处乘以额外的缩放因子
在此配置下,DeepSeek-V3 总共包含671B 个参数,其中每个token 激活37B 个参数
对于训练超参数
他们采用AdamW 优化器(Loshchilov 和Hutter,2017),其超参数设置为β1 = 0.9, β2 =0.95,权重衰减= 0.1
在预训练期间,将最大序列长度设置为4K,并在14.8T 的标记上预训练DeepSeek-V3
对于学习率调度
- 首先在前2 K 步中将其从0 线性增加到2.2 × 10−4
- 然后,保持恒定的学习率2.2 × 10−4,直到模型消耗10T 训练token
- 随后,在4.3T token中逐渐将学习率衰减到2.2 × 10−5,遵循余弦衰减曲线
- 在最后500B token的训练中,他们在前333B 标记中保持恒定的学习率2.2 × 10−5,并在剩余的167B token中切换到另一个恒定学习率7.3 × 10−6
梯度剪辑范数设置为1.0,至于其他的
- 他们那采用批量大小调度策略,在前469B 标记的训练中,批量大小逐渐从3072 增加到15360,然后在剩余训练中保持15360
- 且利用流水线并行性将模型的不同层部署在不同的GPU 上,对于每一层,路由的专家将均匀部署在属于8 个节点的64 个GPU 上
- 对于节点限制路由,每个标记最多将被发送到4 个节点(即,M = 4)
- 对于无辅助损失的负载平衡,将偏置更新速度γ 设置为0.001,用于前14.3T 标记,并在剩余的500B token中设置为0.0
- 对于平衡损失,我们将α 设置为0.0001,以避免在任何单一序列中出现极端不平衡
- MTP 损失权重λ 在前10T token中设置为0.3,在剩余的4.8T token中设置为0.1
3.1.3 长上下文扩展
他们采用与DeepSeek-V2(DeepSeek-AI, 2024c)类似的方法,以在DeepSeek-V3 中实现长上下文能力
在预训练阶段之后,应用YaRN「Peng et al., 2023a,或见此文《大模型长度扩展综述:从直接外推ALiBi、插值PI、NTK-aware插值(对此介绍最详)、YaRN到S2-Attention》」进行上下文扩展,并执行两个额外的训练阶段,每个阶段包含1000 步,以逐步将上下文窗口从4 K 扩展到32 K,然后扩展到128 K
YaRN 的配置与DeepSeek-V2 中使用的一致,仅应用于解耦的共享键kRt
超参数在两个阶段中保持相同,规模为s = 40, α = 1, β = 32,缩放因子为√t = 0.1 ln s + 1
- 在第一阶段,序列长度设置为32K,批量大小为1920
- 在第二阶段,序列长度增加到128K,批量大小减少到480。两个阶段的学习率均设置为7.3×10−6,与预训练阶段的最终学习率相匹配
通过这种两阶段扩展训练,DeepSeek-V3 能够处理长度达 128K 的输入,具体如下图图 8 显示,经过监督微调后,DeepSeek-V3 在“针在大海捞针”(NIAH)测试中表现出色——展示了在上下文窗口长度达 128K 时的一致稳健性
3.1.4 评估与讨论
// 待更
3.2 训练后处理:透露了大半后来引爆全球的R1正式版训练流程
3.2.1 监督微调
作者整理了他们的指令微调数据集,包括150万个实例,涵盖多个领域,每个领域采用不同的数据创建方法,以满足其特定需求
3.2.1.1 先做SFT再做RL,类似R1正式版的前两个阶段训练
首先,对于与推理相关的数据集
包括那些专注于数学、代码竞赛问题和逻辑谜题的数据集,他们通过利用内部的DeepSeek-R1模型生成数据
上面这句:“他们通过利用内部的DeepSeek-R1模型生成数据”,就有很有意思了
- 其实本质是
如后来R1正式版发布之后,deepseek的作者之一Daya Guo于25年2月初所说 : “671B 参数的 R1-Zero 和 R1 是在 V3 发布之后才开始跑的,训练大约花了 2-3 周- 之前 V3 技术报告提到的 R1 模型,实际上是 R1-Lite 或者 R1-Lite-Zero”
具体而言,虽然R1生成的数据表现出很高的准确性,但它也存在过度思考、格式不佳和过长等问题,他们的目标是平衡R1生成推理数据的高准确性与常规格式推理数据的清晰性和简洁性
为此,他们首先开发一个针对特定领域(如代码、数学或一般推理)的专家模型,使用监督微调(SFT)和强化学习(RL)相结合的训练流程,这个专家模型作为最终模型的数据生成器——相当于R1正式版4阶段训练中前2个阶段训练后得到的模型
训练过程包括为每个实例生成两种不同类型的SFT样本:
- 第一种将问题与其原始响应配对,格式为<问题,原始响应>;
- 第二种在问题和R1响应中加入系统提示,格式为<系统提示,问题,R1响应>
系统提示经过精心设计,包含指导模型生成具有反思和验证机制的响应的指令
- 在RL阶段,模型利用高温采样生成响应,即使在没有明确系统提示的情况下,也能整合来自R1生成和原始数据的模式
- 经过数百个RL步骤,中间RL模型学会了结合R1模式,从而战略性地提高整体性能
3.2.1.2 SFT RL之后,再采集高质量SFT:相当于R1正式版4阶段训练中的阶段3
在完成RL训练阶段后,作者再实施拒绝采样来策划高质量的SFT数据以用于最终模型,其中专家模型被用作数据生成源——相当于R1正式版4阶段训练中的阶段3
此方法确保最终训练数据保留DeepSeek-R1的优势,同时生成简洁有效的response——如果在这个v3的技术报告中,再直接点明马上要进行第二轮RL,则相当于把后来25年1.20日才发布的R1正式版的4阶段训练过程 直接提前预告了
以上,是不是和后来25年1.20日发布的deepseek R1正式版的训练特别像?「详见此文《一文速览DeepSeek R1:如何通过纯RL训练大模型的推理能力以比肩甚至超越OpenAI o1(含Kimi K1.5的解读)》」
deepseek R1的训练流程,简言之 是微调 → RL → 微调 → RL,具体而言是
- 首先收集了数千个冷启动数据来微调 DeepSeek-V3-Base 模型
- 随后,进行类似 DeepSeek-R1-Zero 的面向推理的强化学习
- 当强化学习过程接近收敛时,通过对 RL 检查点进行拒绝采样,结合 DeepSeek-V3 在写作、事实问答和自我认知等领域的监督数据,创建新的 SFT 数据,然后重新训练DeepSeek-V3-Base 模型
- 在用新数据微调后,检查点会经历额外的 RL 过程——且会考虑到所有场景的提示
相当于deepseek v3技术报告已经把后来引爆全球的R1正式版的4阶段训练过程,透露了一大半,但在R1爆火之前,又有几个人会把v3报告抠的这么细呢,包括我当时也没看这么细——时也、运也..
其次,对于非推理数据
例如创意写作、角色扮演和简单问答,他们使用DeepSeek-V2.5生成response,并邀请人工标注者验证数据的准确性和正确性
最后,对于SFT 设置
他们使用SFT 数据集对DeepSeek-V3-Base 进行微调两个epoch——这和R1正式版4阶段训练过程中的阶段3中的设计是一模一样的
以下内容来自: 《一文速览DeepSeek R1:如何通过纯RL训练大模型的推理能力以比肩甚至超越OpenAI o1(含Kimi K1.5的解读)》
1.3.3 阶段三 V3上的的两轮SFT(结合rejection sampling):涉及80w通用层面的推理和非推理数据
- 当阶段二 面向推理的强化学习RL收敛时,作者利用所得的checkpoint来收集用于下一轮(对应着阶段三)的SFT(监督微调)数据——你是不想问 合着阶段一 阶段二就是为了方便阶段三来收集推理层面的SFT数据?直白点说 不为模型 为推理数据
- 与最初冷启动数据主要关注推理不同,此阶段结合了来自其他领域的数据,以增强模型在写作、角色扮演和其他通用任务方面的能力
- ..
- 然后使用上述大约80万样本的精心整理数据集对DeepSeek-V3-Base进行两轮微调——相当于两个epoch的sft
且采用余弦衰减学习率调度,从5 ×10−6 开始逐渐减少到1 × 10−6。在训练过程中,每个单一序列由多个样本打包
然而,他们采用样本掩码策略以确保这些样本保持隔离和相互不可见
3.2.2 强化学习:涉及奖励模型和GRPO
对于奖励模型,他们在强化学习过程中使用了基于规则的奖励模型(RM)和基于模型的RM
- 基于规则的RM——比如准确率奖励/格式奖励(R1-Zero)、语言一致性奖励(R1 阶段二)
对于可以使用特定规则验证的问题,采用基于规则的奖励系统来确定反馈。例如,某些数学问题有确定性的结果,要求模型在指定格式内(例如,在一个框中)提供最终答案,以便我们应用规则来验证正确性
同样,对于LeetCode问题,可以利用编译器根据测试用例生成反馈
通过尽可能使用基于规则的验证,从而确保更高的可靠性,因为这种方法对操控或利用具有抵抗力 - 基于模型的RM
在具有自由形式真实答案的问题中,依赖奖励模型来确定响应是否符合预期的真实答案
相反,对于那些没有明确真实答案的问题,例如涉及创意写作的问题,奖励模型的任务是根据输入的问题和相应的答案提供反馈
奖励模型从DeepSeek-V3 SFT检查点进行训练
为了提高其可靠性,作者构建了偏好数据,这些数据不仅提供最终奖励,还包括通向奖励的思维链。这种方法有助于降低在特定任务中奖励作弊的风险——这是R1正式版4阶段训练过程中的阶段4 是一样的
以下内容来自: 《一文速览DeepSeek R1:如何通过纯RL训练大模型的推理能力以比肩甚至超越OpenAI o1(含Kimi K1.5的解读)》
1.3.4 阶段四 所有场景的RL:提高有用性和无害性,且混合规则奖励和偏好奖励
为了进一步使模型符合人类偏好,作者实施了一个辅助的强化学习阶段——相当于第二轮RL,旨在提升模型的有用性和无害性,同时优化其推理能力具体来说,作者使用奖励信号和多样的提示分布组合来训练模型
- 对于推理数据
作者遵循DeepSeek-R1-Zero中概述的方法,该方法利用基于规则的奖励(rule-based reward)来指导数学、代码和逻辑推理领域的学习过程
For reasoning data, we adhere to themethodology outlined in DeepSeek-R1-Zero, which utilizes rule-based rewards to guide thelearning process in math, code, and logical reasoning domains- 对于一般数据
作者使用奖励模型来捕捉复杂和微妙场景中的人类偏好——preference reward。比如基于DeepSeek-V3流程,采用类似的偏好对和训练提示的分布
对于RL方法,如上文所说,V3继续采用的群体相对策略优化
类似于DeepSeek-V2 (DeepSeek-AI, 2024c),V3继续 采用了Group Relative Policy Optimization (GRPO)(Shao et al., 2024),该方法放弃了通常与策略模型大小相同的critic模型,而是从组得分中估计baseline
具体来说,对于每个问题,GRPO 从旧策略模型
中采样一组输出
,然后通过最大化以下目标来优化策略模型
其中,ε 和β 是超参数; 是参考模型;
是从每组内输出对应的奖励
导出的优势:
作者在强化学习过程中引入了来自不同领域的提示,如编码、数学、写作、角色扮演和问答。这种方法不仅使模型更符合人类偏好,还提高了基准测试的性能,尤其是在可用的监督微调数据有限的情况下
关于GRPO的介绍,更多详见《一文速览DeepSeekMath及GRPO:通俗理解群体相对策略优化GRPO(含DeepSeek-Coder的简介)》
3.2.3 评估与讨论:关于DeepSeek-R1提炼与多token预测
对于从DeepSeek-R1提炼
他们基于DeepSeek-V2.5对DeepSeek-R1的蒸馏贡献进行了消融实验——相当于用V2.5的base模型去PK 拒绝采样R1-Lite生成的推理数据做SFT
基线是在短CoT数据上训练的,而其竞争对手使用的是上文《3.2.1.1 先做SFT再做RL,类似R1正式版的前两个阶段训练》所述的专家检查点生成的数据
表9展示了蒸馏数据的有效性,在LiveCodeBench和MATH-500基准测试中显示出显著的改进
该实验揭示了一个有趣的权衡:蒸馏导致更好的性能,但也大大增加了平均response长度
为了在模型准确性和计算效率之间保持平衡,他们精心选择了DeepSeek-V3在蒸馏中的最佳设置
且研究表明
- 从推理模型中提取知识是训练后优化的一个有前途的方向——所以R1 训练过程的前两个阶段的本质就是训练一个推理模型(先SFT 后RL),然后再基于该推理模型拒绝采样出更高质量的SFT数据
- 虽然他们目前的工作重点是从数学和编程领域提取数据,但这种方法在各种任务领域中显示出更广泛应用的潜力。在这些特定领域中展示的有效性表明,长链推理(long-CoT)提取可能对增强其他需要复杂推理的认知任务的模型性能具有价值
当然了,在不同领域进一步探索这一方法仍然是未来研究的一个重要方向
对于多token预测
与其仅预测下一个单一token,DeepSeek-V3 通过MTP 技术预测下两个token,结合推测解码框架(Leviathan et al., 2023; Xia et al., 2023),它可以显著加快模型的解码速度
一个自然的问题是关于额外预测token的接受率。根据他们的评估,第二个token预测的接受率在各种生成主题中介于85 % 到90% 之间,表现出一致的可靠性。这种高接受率使得DeepSeek-V3 能够实现显著提高的解码速度,达到1.8 倍的TPS(每秒token数)
// 待更
第四部分 DeepSeek V3所开源的具体内容
一般而言,看一个模型的开源力度,会看4个层面:训练数据、推理数据、训练代码、推理代码,当然 这4个层面中 最重要的则是其中的训练数据和训练代码
根据DeepSeek V3的GitHub可知,V3对外开源的内容如下所示
类别 | 开源内容 | 未开源内容 |
---|---|---|
模型权重 | FP8/BF16 格式的基础模型和聊天版本 相当于开源了FP8 格式模型权重(包含基础模型和聊天优化版本),支持通过脚本转换为 BF16 格式进行推理——用户可通过 Hugging Face 平台直接下载 | 训练数据 数据清洗、预处理代码或数据集链接,比如 14.8 万亿 Token 的预训练数据集或具体数据来源 |
架构代码 | 包含模型定义的核心代码(如model.py),比如MLA、DeepSeekMoE、MTP 模块实现,但仅限架构定义,不包含完整的训练流程 | 从 DeepSeek-R1 提取知识的详细实现也未提供 |
训练框架 | FP8 混合精度框架、上下文扩展工具 | 完整分布式训练代码、超参数配置 比如分布式训练框架(如 DualPipe 流水线并行)、FP8 混合精度训练的具体实现 |
推理工具 | 主流框架适配方案、Hugging Face 示例 即提供基于 Hugging Face 或 vLLM 的简单推理脚本(如 inference.py),但未公开生产级优化代码(如动态批处理、显存优化等) | 生产级优化内核 比如企业级部署工具(如 DeepSeek 自研的推理引擎),涉及动态批处理、显存管理等等 |
从上可以看到,V3的训练代码,包括MTP技术的实现代码都均未开源,那咋办呢?
请见此文《R1复现之路[上]——首先复现DeepSeek V3:在V3官方代码库对MoE、MLA的实现之外,补充我对多token预测MTP的实现》