【论文笔记】DeepSeek-V3 Technical Report

Posted by Masutangu on February 6, 2025

本文是《DeepSeek-V3 Technical Report》的笔记。

Abstract

DeepSeek-V3 是一个强大的混合专家(Mixture-of-Experts,MoE)语言模型,总参数量为 671B,每个 token 激活 37B 参数。为了实现高效的推理和经济高效的训练,DeepSeek-V3 采用了多头潜在注意力(Multi-head Latent Attention,MLA)DeepSeekMoE 架构,这在 DeepSeek-V2 中得到了充分验证。DeepSeek-V3 开创了一种无辅助损失的负载平衡策略(auxiliary-loss-free strategy for load balancing),并设定了多 token 预测(multi-token prediction, MTP)训练目标以提升性能。我们在 14.8 万亿多样且高质量 token 上对 DeepSeek-V3 进行预训练,随后进行监督微调(Supervised Fine-Tuning)强化学习(Reinforcement Learning)以充分发挥其能力。综合评估显示,DeepSeek-V3 超过了其他开源模型,并达到了与领先闭源模型相当的性能。尽管性能优异,DeepSeek-V3 的完整训练仅需 2.788M H800 GPU 小时。此外,其训练过程非常稳定,在整个训练过程中没有遇到任何不可恢复的损失峰值或进行任何回滚。

1. Introduction

在架构方面,DeepSeek-V3 仍然采用多头潜在注意力(MLA)用于高效推理,以及 DeepSeekMoE 用于经济高效的训练。这两种架构已在 DeepSeek-V2 中得到验证,证明它们在实现高效训练和推理的同时能够保持稳健的模型性能。除了基本架构之外,我们还实施了两种额外的策略来进一步增强模型的能力。首先,DeepSeek-V3 引入了一种无辅助损失的策略用于负载平衡,旨在最大限度地减少由于鼓励负载平衡而产生对模型性能的不利影响。其次,DeepSeek-V3 采用了多 token 预测训练目标,我们观察到这可以整体提高性能。

为了实现高效的训练,我们支持 FP8 混合精度训练,并对训练框架进行全面的优化。低精度训练已经成为高效训练的一种有前景的解决方案,其发展与硬件能力的进步密切相关。在这项工作中,我们引入了 FP8 混合精度训练框架,并首次验证了其在极大规模模型上的有效性。通过对 FP8 计算和存储的支持,我们实现了训练加速和减少 GPU 内存使用。至于训练框架,我们设计了 DualPipe 算法用于高效的管道并行,其具有较少的管道停顿(pipeline bubbles),并通过计算-通信重叠(computation-communication overlap)隐藏了训练过程中的大部分通信。这确保了随着模型的进一步扩大,只要保持恒定的计算-通信比,我们仍然可以在节点间使用细粒度的专家,并实现接近零的全互连通信开销。此外,我们还开发了高效的跨节点全互连通信内核,以充分利用 InfiniBand(IB)和 NVLink 的带宽。此外,我们还精心优化了内存占用,使得在训练 DeepSeek-V3 时不需要使用昂贵的张量并行(tensor parallelism)。通过结合这些努力,我们实现了高效的训练效率。

在预训练阶段,我们使用了 14.8 T个高质量和多样化的标记。接下来,我们进行两阶段的上下文长度扩展。在第一阶段,最大上下文长度扩展到 32K,在第二阶段进一步扩展到 128 K。在此之后,我们进行后训练,包括对 DeepSeek-V3 基础模型的监督微调(SFT)和强化学习(RL),以使其与人类偏好保持一致并进一步发挥其潜力。在后训练阶段,我们从 DeepSeekR1 系列模型中蒸馏了推理能力,同时在模型准确性和生成长度之间维持好平衡。

我们的主要贡献包括:

  • 架构:创新的负载平衡策略和训练目标
    • 在 DeepSeek-V2 架构的基础上,首创了一种无辅助损失的负载平衡策略,最大限度地减少了由于鼓励负载平衡而导致的性能下降
    • 研究了多 token 预测(MTP)目标,并证明它对模型性能有益。它还可以用于推测解码(speculative decoding)以加速推理
  • 预训练:追求终极训练效率
    • 我们设计了一个 FP8 混合精度训练框架,并首次验证了在极大规模模型上进行 FP8 训练的可行性和有效性
    • 通过算法、框架和硬件的协同设计,我们克服了跨节点 MoE 训练中的通信瓶颈,实现了接近完全的计算-通信重叠。这显著提高了我们的训练效率,降低了训练成本
    • 仅以 2.664M H800 GPU 小时的经济成本,我们完成了 DeepSeek-V3 在 14.8T 标记上的预训练,生成了目前最强大的开源基础模型。预训练后的后续训练阶段仅需要 0.1M GPU 小时。
  • 后训练:从 DeepSeek-R1 进行知识蒸馏
    • 我们引入了一种创新的方法,从长链思维(CoT)模型(DeepSeek R1 系列模型)提取出推理能力,蒸馏到标准 LLM (DeepSeek-V3 模型)中。我们的流程巧妙地将 R1 模型的验证和反思模式整合到 DeepSeek-V3 中,显著提高了其推理性能。与此同时,我们还能够控制 DeepSeek-V3 的输出风格和长度。

2. 架构

2.1 基本架构

DeepSeek-V3 的基本架构仍然在 Transformer 框架内。DeepSeek-V3 采用了已经被 DeepSeek-V2 彻底验证过的 MLA 和 DeepSeekMoE。并额外引入了一种无辅助损失的负载均衡策略。

图 1:DeepSeek-V3 基本架构的示意图。遵循 DeepSeek-V2,我们采用 MLA 和 DeepSeekMoE 来实现高效的推理和经济的训练。

2.1.1.多头潜在注意力

对于注意力机制,DeepSeek-V3 采用了 MLA 架构。设 $d$ 表示嵌入维度,$n_h$ 表示注意力头的数量,$d_h$ 表示每个头的维度,$h_t \in R^d$ 表示给定注意力层中第 $t$ 个token 的注意力输入。MLA 的核心是对注意力键和值进行低秩联合压缩(low-rank joint compression),以减少推理过程中的键值(KV)缓存:

\[\begin{align*} c_t^{KV} &= W^{DKV}h_t \\ [k^C_{t,1}; k^C_{t,2}; ...; k^C_{t,n_h}] &= k^C_{t} = W^{UK}c_t^{KV} \\ k_{t}^{R} &= RoPE(W^{KR}h_{t}) \\ k_{t,i} &= [k^C_{t,i}; k_{t}^{R}] \\ [v^C_{t,1}; v^C_{t,2}; ...; v^C_{t,n_h}] &= v^C_{t} = W^{UK}c_t^{KV} \end{align*}\]

其中 $c_t^{KV} \in R^{d_c}$ 是键和值的压缩潜在向量(compressed latent vector);$d_c (≪ d_{h}n_{h})$ 表示 KV 压缩维度;$W^{DKV} \in R^{d_c \times d}$ 是键和值的下投影矩阵;$W^{UK}, W^{UV} \in R^{d_h n_h \times d_c}$ 分别是键和值的上投影矩阵;$W^{KR} \in R^{d^R_{h} \times d}$ 是用来生成带旋转位置嵌入(RoPE)的解耦键的矩阵。

对于 MLA,生成过程中只有向量 $c^{KV}_t$ 和 $k_t^R$ 需要缓存,这导致 KV 缓存显著减少,同时保持与标准多头注意力相当的性能。

对于注意力查询,我们也执行低秩压缩,这可以在训练期间减少激活内存:

\[\begin{align*} c_{t}^{Q} &= W^{DQ}h_t \\ [q^C_{t,1}; q^C_{t,2}; ...; q^C_{t,n_h}] &= q^C_{t} = W^{UQ}c_t^{Q} \\ [q^R_{t,1}; q^R_{t,2}; ...; q^R_{t,n_h}] &= q^R_{t} = RoPE(W^{QR}c_t^{Q}) \\ q_{t,i} &= [q^C_{t,i}; q_{t}^{R}] \end{align*}\]

其中 $c_{t}^{Q} \in R^{d_c’}$ 是查询的压缩潜在向量;$d_c’(≪ d_h n_h)$ 表示查询压缩维度;$W^{DQ} \in R^{d_c’ \times d}$ 是查询的下投影矩阵;$W^{UQ} \in R^{d_h n_h \times d_c’}$ 是查询的上投影矩阵;$W^{QR} \in R^{d^R_h n_h \times d_c’} $是用来生成带 RoPE 的解耦查询的矩阵。

最终,注意力查询($q_{t,i}$),键($k_{j,i}$) 和值 ($v_{j,i}^{C}$) 被组合产生最终的注意力输出 $u_t$:

\[\begin{align*} \mathbf{o}_{t,i} &= \sum_{j=1}^{t}\mathrm{Softmax}_{j}(\frac{\mathbf{q}_{t,i}^{T}\mathbf{k}_{j,i}}{\sqrt{d_{h}+d_{h}^{R}}})\mathbf{v}_{j,i}^{C} \\ \mathbf{u}_{t} &= W^{O}[\mathbf{o}_{t,1};\mathbf{o}_{t,2};...;\mathbf{o}_{t,n_{h}}] \end{align*}\]

其中 $W^{O} \in R^{d_{o} \times d_{h}}$ 表示输出投影矩阵。

2.1.2. Deepseekmoe With Auxiliary-Loss-Free Load Balancing

DeepSeekMoE的基本架构

对于前馈网络(Feed-Forward Networks,FFNs),DeepSeek-V3 采用了 DeepSeekMoE 架构。与传统的 MoE 架构(例如 GShard)相比,DeepSeekMoE 使用更细粒度的专家,并将一些专家隔离为共享专家。设 $u_t$ 表示第 t 个 token 的 FFN 输入,我们按以下方式计算 FFN 输出 $h_t’$:

\[\begin{align*} \mathbf{h}_{t}^{\prime}&=\mathbf{u}_{t}+\sum_{i=1}^{N_{t}}\mathrm{FFN}_{i}^{(s)}(\mathbf{u}_{t})+\sum_{i=1}^{N_{r}}g_{i,t}\mathrm{FFN}_{i}^{(r)}(\mathbf{u}_{t}) \\ g_{i,t}&=\frac{g_{i,t}^{\prime}}{\sum_{j=1}^{N_{r}}g_{j,t}^{\prime}} \\ g_{i,t}^{\prime}&=\begin{cases}s_{i,t},&s_{i,t}\in\mathrm{Topk}(\{s_{j,t}|1\leqslant j\leqslant N_{r}\},K_{r}),\\ 0,&\text{otherwise},\end{cases} \\ s_{i,t}&=\mathrm{Sigmoid}\left(\mathbf{u}_{t}^{T}\mathbf{e}_{i}\right), \end{align*}\]

其中,$N_s$ 和 $N_r$ 分别表示共享专家和路由专家的数量;$\mathrm{FFN}^{(s)}(\cdot)$ 和 $\mathrm{FFN}^{(r)}(\cdot)$ 分别表示第 i 个共享专家和第 i 个路由专家;$K_r$ 表示激活的路由专家的数量;$g_{i,t}$ 是第 i 个专家的门控值;$s_{i,t}$ 是 token 到专家的亲和力(token-to-expert affinity);$e_i$ 是第 i 个路由专家的质心向量(centroid vector);$\mathrm{Topk}(\cdot, K)$ 表示在为第 t 个 token 和所有路由专家计算的亲和力得分中选取最高 $K$ 个得分的集合。DeepSeek-V3 与 DeepSeek-V2 略有不同,使用 sigmoid 函数来计算关联得分,并对所有选定的关联得分进行归一化,以生成门控值。

无辅助损失的负载均衡

对于 MoE 模型,专家负载不平衡会导致路由崩溃,并在专家并行场景中降低计算效率。传统解决方案通常依赖于辅助损失来避免负载不平衡。然而,过大的辅助损失会损害模型性能。为了在负载均衡和模型性能之间取得更好的平衡,我们首创了一种无辅助损失的负载均衡策略来确保负载均衡。具体来说,我们为每个专家引入一个偏置项,并将其加到相应的亲和力得分上,以确定前 K 个路由:

\[g^{\prime}_{i,t}=\begin{cases}s_{i,t},&s_{i,t}+b_{i}\in\text{Topk}(\{s_{j,t}+b_{j}|1\leqslant j\leqslant N_{r}\},K_{r}),\\ 0,&\text{otherwise}.\end{cases}\]

注意,偏置项仅用于路由。门控值仍然来自原始亲和力得分$s_{i,t}$。在训练过程中,我们持续监控每个训练步骤中整个批次的专家负载。在每个步骤结束时,如果其对应的专家过载,我们将减少偏置项,如果其对应的专家欠载,我们将增加偏置项。通过动态调整,DeepSeek-V3 在训练期间保持专家负载平衡,并比通过纯辅助损失鼓励负载平衡的模型取得更好的性能。

补充的序列级辅助损失

尽管 DeepSeek-V3 主要依靠无辅助损失策略进行负载均衡,但为了防止任何单个序列内的极端不平衡,我们还采用了补充的序列级平衡损失。序列级平衡损失鼓励每个序列上的专家负载平衡。

节点限制路由

类似于 DeepSeek-V2 使用的设备限制路由,DeepSeek-V3 也使用了一种受限路由机制来限制训练期间的通信成本。简而言之,我们确保每个 token 最多只会被发送到 M 个节点,这些节点是根据分布在每个节点上的专家的最高 $\frac{K_r}{M}$ 个关联得分之和来选择的。在这种约束下,我们的 MoE 训练框架几乎可以实现完全的计算-通信重叠。

无token丢弃

由于有效的负载均衡策略,DeepSeek-V3 在其全部训练期间保持了良好的负载均衡。因此,DeepSeek-V3 在训练期间不会丢弃任何 token。此外,我们还实施了特定的部署策略以确保推理负载均衡,因此DeepSeek-V3 在推理期间也不会丢弃 token。

2.2 多令牌预测

受 Gloeckle 等人的启发,我们为 DeepSeek-V3 研究并设置了一个多 token 预测目标,该目标将每个位置的预测范围扩展到未来多个 token。一方面,MTP 目标使训练信号更加密集,可能会提高数据效率。另一方面,MTP 可能使模型能够预先规划其表示,以更好地预测未来的 token。下图展示了我们的 MTP 实现。与 Gloeckle 等人不同的是,他们使用独立的输出头并行预测额外的 D 个token,我们顺序预测额外的 token,并保留每个深度的完整因果链。

图2:多 token 预测实现的示意图。我们在每个深度保留了每个 token 预测的完整因果链。

MTP 模块

具体来说,我们的 MTP 实现使用 D 个顺序模块来预测 D 个 token。第 k 个 MTP 模块由一个共享的嵌入层 $Emb(·)$、一个共享的输出头 $OutHead(·)$、一个 Transformer 块 $TRM_k(·)$ 和一个投影矩阵 $M_k \in R^{d \times 2d}$ 组成。对于第 i 个输入令牌,在第 k 个预测深度,我们首先将第 i 个令牌在第 (k-1) 个深度的表示 $h_{i}^{k-1} \in R^d$ 与第 (i+k) 个令牌的嵌入 $Emb(t_{i+k}) \in R^d$ 通过线性投影结合起来:

\[\mathbf{h'}_{i}^{k}=M_{k}[\mathrm{RMSNorm}(\mathbf{h}_{i}^{k-1}); \mathrm{RMSNorm}(\mathrm{Emb}(t_{i+k}))],\]

当 $k = 1$ 时,$h_{i}^{k-1}$ 即主模型给出的表示。注意,对于每个 MTP 模块,其嵌入层与主模型共享。结合后的表示 $h’^k_i$ 作为第 k 个深度的 Transformer 块的输入,用于生成当前深度的输出表示 $h^k_j$:

\[{\bf h}_{1:T-k}^{k}=\mathrm{TRM}_{k}({\bf h}_{1:T-k}^{\prime k}),\]

其中,$T$ 表示输入序列的长度,$i:j$ 表示切片操作(包括左右边界)。最后,以 $h^k_j$ 作为输入,共享的输出头将计算第 k 个额外预测 token $P^k_{i+1+k} \in R^V$ 的概率分布,其中 $V$ 是词汇表的大小:

\[P_{i+k+1}^{k}=\mathrm{OutHead}(\mathbf{h}_{i}^{k}).\]

输出头 $OutHead(·)$ 将表示映射为 logits,并随后应用 $Softmax(·)$ 函数来计算第 𝑘 个额外令牌的预测概率。对于每个 MTP 模块,其输出头与主模型共享。我们保持预测的因果链的原则和 EAGLE 相似,其主要目标是推测解码,而我们利用 MTP 来改进训练。

MTP 训练目标

对于每个预测深度,我们计算一个交叉熵损失 $\mathcal{L}_{MTP}$:

\[{\mathcal{L}}_{\mathrm{MTP}}^{k}=\mathrm{CrossEntropy}(P_{2+k:T+1}^{k},t_{2+k:T+1})=-\frac{1}{T}\sum_{i=2+k}^{T+1}\log P_{i}^{k}[t_{i}],\]

其中 T 表示输入序列长度,$t_{i}$ 表示第 i 个位置的真实令牌,$P_{i}^{k}[t_i]$ 表示由第 k 个 MTP 模块给出的 $t_i$ 相应预测概率。最后,我们计算所有深度上 MTP 损失的平均值,并乘以一个权重因子 λ 得到整体的 MTP 损失作为 DeepSeek-V3 的额外训练目标:

\[{\mathcal{L}}_{\mathrm{MTP}}={\frac{\lambda}{D}}\sum_{k=1}^{D}{\mathcal{L}}_{\mathrm{MTP}}^{k}.\]

推理的 MTP

我们的 MTP 策略主要旨在提高主模型的性能,因此在推理过程中,我们可以直接丢弃 MTP 模块,主模型可以独立正常地运行。此外,我们还可以重新利用这些 MTP 模块进行推测性解码,以进一步改善生成延迟。

基础设施

3.1. Compute Clusters

DeepSeek-V3 在一个配备 2048 个 NVIDIA H800 GPU 的集群上进行训练。H800 集群中的每个节点包含 8 个通过 NVLink 和节点内的 NVSwitch 连接的 GPU。在不同节点之间,使用 InfiniBand (IB) 互连来促进通信。

3.2. 训练框架

DeepSeek-V3 的训练由 HAI-LLM 框架支持,这是一个由我们的工程师从零打造的高效轻量级训练框架。总体上,DeepSeek-V3 应用了 16 路流水线并行(Pipeline Parallelism,PP)、跨越 8 个节点的 64 路专家并行(Expert Parallelism,EP)以及 ZeRO-1 数据并行(Data Parallelism,DP)

3.2.1. Dualpipe 和计算-通信重叠

对于 DeepSeek-V3,跨节点专家并行性引入的通信开销导致了大约 1:1 的低效计算到通信比率。为了解决这个挑战,我们设计了一种创新的管道并行算法,称为 DualPipe。其减少了管道气泡,更重要的是,它在前向和反向过程中重叠了计算和通信阶段,从而解决了跨节点专家并行引入的大量通信开销的挑战。

图3:一对独立的前向和反向块的重叠策略。橙色表示前向,绿色表示“反向输入”,蓝色表示“反向权重”,紫色表示管道并行通信,红色表示屏障。全互连和管道并行通信都可以完全隐藏。

DualPipe 的关键思想是在一对独立的前向和后向块内重叠计算和通信。具体来说,我们将每个块分为四个组件:注意力(attention)、全连接分发(all-to-all dispatch)、MLP 和全连接组合(all-to-all combine)。对于反向块,注意力和 MLP 进一步分为两个部分:输入的 backward 和权重的 backward,类似于 ZeroBubble。此外,我们还有一个 PP 通信组件。如上图所示,对于一对前向和后向块,我们重新排列这些组件,并手动调整专用于通信与计算的 GPU SM 的比例。在这种重叠策略中,我们可以确保在执行期间全连接和 PP 通信都可以完全隐藏。鉴于这种有效的重叠策略,完整的 DualPipe 调度如下图所示,它采用双向管道调度,同时从管道的两端提供微批次,可以实现通信的大部分内容完全重叠。这种重叠还确保了,随着模型的进一步扩展,只要我们保持恒定的计算到通信比率,我们仍然可以在节点间使用细粒度的专家,同时实现接近零的全连接通信开销。

图4:8 个 PP 排名和两个方向上 20 个微批次的 DualPipe 调度示例。

3.2.2. 高效实现跨节点全互连通信

为了确保 DualPipe 具有足够的计算性能,我们定制了高效的跨节点全连接通信内核(包括 dispatching 和 combining),以减少用于通信的流式多处理器(SM)数量。内核的实现与我们的 MoE 门控算法和集群的网络拓扑进行了协同设计。具体而言,在我们的集群中,跨节点的GPU通过IB完全互连,节点内的通信通过 NVLink 处理。NVLink 提供了 160 GB/s的带宽,大约是 IB(50 GB/s)的 3.2 倍。为了有效利用 IB 和 NVLink 的不同带宽,我们将每个令牌限制为最多分发到 4 个节点,从而减少 IB 的流量。对于每个令牌,在进行路由决策时,它将首先通过 IB 传输到目标节点。一旦到达目标节点,我们将努力确保它通过 NVLink 立即转发到托管其目标专家的特定 GPU,而不会被随后到达的令牌阻塞。通过这种方式,通过 IB 和 NVLink 的通信完全重叠,并且每个令牌可以在不产生额外 NVLink 开销的情况下高效选择平均 3.2 个节点的专家。这意味着,尽管 DeepSeek-V3 在实践中只选择了8个路由的专家,但它可以将这个数量最大扩展到13个专家(4个节点×每个节点3.2个专家),同时保持相同的通信成本。总体而言,在这种通信策略下,只需要 20 个 SM 就足以充分利用 IB 和 NVLink 的带宽。

3.2.3. 极度节省内存且开销极小

为了在训练期间减少内存占用,我们采用以下技术。

重新计算 RMSNorm 和 MLA 向上投影:在反向传播过程中,重新计算所有的 RMSNorm 操作和 MLA 向上投影,从而避免持久存储其输出激活。通过较小的开销显著减少了存储激活所需的内存。

在 CPU 中维护 EMA:在训练期间,保留模型参数的指数移动平均(Exponential Moving Average,EMA)以用于学习率衰减后对模型性能的早期估计。EMA 参数存储在 CPU 内存中,并在每个训练步骤之后异步更新。这种方法允许我们在不增加额外内存或时间开销的情况下维护 EMA 参数。

多令牌预测的共享嵌入和输出头:使用 DualPipe 策略,将模型的最浅层(包括嵌入层)和最深层(包括输出头)部署在同一 PP rank 上,使 MTP 模块和主模型之间能够物理共享参数和梯度,即共享嵌入和输出头。这种物理共享机制进一步提高了我们的内存效率。

3.3. Fp8 Training

受到低精度训练的最新进展的启发,我们提出了一种细粒度的混合精度框架,利用 FP8 数据格式来训练 DeepSeek-V3。尽管低精度训练具有巨大的潜力,但通常受到激活、权重和梯度中异常值的限制。为了应对这一挑战并有效扩展FP8格式的动态范围,我们引入了一种细粒度的量化策略:以 $1 \times N_c$ 元素进行块内分组或以 $N_c \times N_c$ 元素进行块间分组。在我们增加精度的累积过程中,相关的反量化开销在很大程度上得到缓解,这是实现准确的 FP8 通用矩阵乘法(GEMM)的关键方面。此外,为了进一步减少 MoE 训练中的内存和通信开销,我们以 FP8 格式缓存和分发激活,同时将低精度优化器状态存储为BF16。与 BF16 基准相比,我们的 FP8 训练模型的相对损失误差始终保持在 0.25% 以下,这个水平远远低于训练随机性的可接受范围。

3.3.1. 混合精度框架

在广泛采用的低精度训练技术的基础上,我们提出了一个用于 FP8 训练的混合精度框架。在这个框架中,大多数计算密集型操作都以 FP8 进行,而一些关键操作则策略性地保持在其原始数据格式中,以平衡训练效率和数值稳定性。整个框架如下图所示。

图5:整体的混合精度框架采用FP8数据格式。为简化说明,只有线性操作符被说明了。

首先,为了加速模型训练,大部分核心计算核心,即 GEMM 操作,采用 FP8 精度实现。这些 GEMM 操作接受 FP8 张量作为输入,并产生 BF16 或 FP32 的输出。如上图所示,与线性操作符相关的三个 GEMM 操作,即 Fprop(前向传播)、Dgrad(激活反向传播)和 Wgrad(权重反向传播),都在 FP8 中执行。这种设计理论上将计算速度与原始的 BF16 方法相比提高了一倍。此外,FP8 的 Wgrad GEMM 允许将激活值存储为 FP8,以供反向传播使用。这显著减少了内存消耗。

尽管 FP8 格式具有效率优势,但由于其对低精度计算的敏感性,某些运算符仍然需要更高的精度。此外,一些低成本运算符也可以使用更高的精度,而对整体训练成本几乎没有影响。我们保留了以下组件的原始精度:嵌入模块、输出头、MoE 门控模块、归一化运算符和注意力运算符。为了进一步保证数值稳定性,我们将主权重、权重梯度和优化器状态存储在更高精度中。

3.3.2. 通过量化和乘法的改进精度

基于我们的混合精度 FP8 框架,我们引入了几种策略来提高低精度训练的准确性,重点关注量化方法和乘法过程。

细粒度量化

在低精度训练框架中,由于 FP8 格式的动态范围受限于其较少的指数位数,overflow 和 underflow 是常见的挑战。作为一种标准做法,通过将输入张量的最大绝对值缩放到 FP8 的最大可表示值,将输入分布对齐到 FP8 格式的可表示范围内。这种方法使得低精度训练对激活值的异常值非常敏感,这可能严重降低量化的准确性。为了解决这个问题,我们提出了一种细粒度量化方法,它在更细粒度的级别上应用缩放。如下图(a)所示,对于激活值,我们以 1x128 tile 为基础(即每个标记每 128 个通道),对元素进行分组和缩放;对于权重,我们以 128x128 block 为基础(即每 128 个输入通道每 128 个输出通道),对元素进行分组和缩放。这种方法确保量化过程可以更好地适应异常值,通过根据更小的元素组进行缩放来调整尺度。

图6:(a) 我们提出了一种细粒度的量化方法来减轻由特征异常值引起的量化误差;为了简化说明,只展示了 Fprop。 (b) 结合我们的量化策略,我们通过在每个高精度累加的间隔处将其提升为 CUDA 核心,改进了 FP8 GEMM 的精度,其中间隔为 NC = 128 个元素的 MMA。

提高累加精度

低精度的 GEMM 操作经常遭受 underflow 问题,并且它们的准确性在很大程度上取决于高精度的累加,通常以 FP32 精度执行。然而,我们观察到在 NVIDIA H800 GPU 上,FP8 GEMM 的累加精度受限,大约只能保留 14 位,远低于 FP32 的累加精度。当内部维度 K 很大时,这个问题会变得更加明显,这是大规模模型训练中的典型情况,其中批量大小和模型宽度增加。尽管存在这些问题,受限的累加精度仍然是一些 FP8 框架的默认选项,严重限制了训练的准确性。

为了解决这个问题,我们采用了提升到 CUDA 核心以获得更高精度的策略。该过程见图6(b)中的说明。具体而言,在 Tensor Cores 上执行 MMA 时,中间结果使用有限的位宽进行累加。一旦达到 $N_C$ 的间隔,这些部分结果将被复制到 CUDA 核心上的 FP32 寄存器中,进行完整精度的 FP32 累加。正如之前提到的,我们的细粒度量化在内部维度 K 上应用了每组的缩放因子。这些缩放因子可以在 CUDA 核心上以最小的额外计算成本进行乘法运算,作为去量化过程的一部分。

这种修改降低了单个 warp 组的 WGMMA(Warpgroup-level Matrix Multiply-Accumulate)指令发出率。然而,在 H800 架构上,通常会同时存在两个 WGMMA:一个 warp 组执行 promotion 操作,另一个可以执行 MMA 操作。这种设计使得这两个操作可以重叠,保持 Tensor Cores 的高利用率。根据我们的实验,设置 $N_C = 128$ 个元素,相当于 4 个 WGMMA,代表了可以显著提高精度而不引入实质性开销的最小累加间隔。

尾数优于指数

之前的工作采用的混合 FP8 格式在 Fprop 中使用 E4M3(4位指数和3位尾数),在 Dgrad 和 Wgrad 中使用 E5M2(5位指数和2位尾数),而我们在所有张量上采用 E4M3 格式以获得更高的精度。我们将这种方法的可行性归因于我们的细粒度量化策略,即 tile 和 block 级别的缩放。通过对较小的元素组进行操作,我们的方法有效地在这些分组元素之间共享指数位,减轻了有限动态范围的影响。

实时量化

在张量级量化框架中,采用了延迟量化的方法,通过维护先前迭代中最大绝对值的历史记录来推断当前值。为了确保准确的尺度并简化框架,我们实时计算每个 1x128 的激活 tile 或 128x128 的权重 block 最大绝对值。基于这个值,我们推导出缩放因子,然后将激活或权重实时量化为 FP8 格式。

3.3.3. 低精度存储和通信

结合我们的 FP8 训练框架,我们通过将缓存的激活和优化器状态压缩为低精度格式,进一步减少了内存消耗和通信开销。

低精度优化器状态

我们采用 BF16 数据格式而不是 FP32 来跟踪 AdamW 优化器中的一阶和二阶矩,而不会引起可观察的性能下降。优化器存储的主权重和用于批量大小累积的梯度仍然保留在 FP32 中,以确保训练期间的数值稳定性。

低精度激活

如图 6 所示,Wgrad 操作在 FP8 中执行。为了减少内存消耗,Linear 运算符的反向传播中以 FP8 格式缓存激活。另外对以下几个运算符进行了特殊考虑以实现低成本的高精度训练:

  1. 注意力运算符后的 Linear 输入: 这些激活也用于注意力运算符的反向传播,这使得它们对精度敏感。我们为这些激活采用定制的 E5M6 数据格式。

  2. MoE 中 SwiGLU 运算符的输入: 为了进一步减少内存成本,我们缓存 SwiGLU 运算符的输入并在反向传播中重新计算其输出。这些激活也使用我们的细粒度量化方法存储在 FP8 中,在内存效率和计算精度之间取得平衡。

低精度通信

通信带宽是训练 MoE 模型的一个关键瓶颈。为了缓解这一挑战,我们在 MoE 向上投影之前将激活量化为 FP8,然后应用 dispatch 组件,这与 MoE 向上投影中的 FP8 Fprop 兼容。像注意力运算符后的 Linear 输入一样,这种激活的缩放因子是 2 的整数幂。类似的策略也应用于 MoE 向下投影前的激活梯度。对于前向和后向 combine 组件,我们将它们保留在 BF16 中,以在训练流程的关键部分保持训练精度。

3.4 推理与部署

我们将 DeepSeek-V3 部署在 H800 集群上,其中每个节点内的 GPU 使用 NVLink 相互连接,而集群中的所有 GPU 通过 IB 完全互联。为了同时确保在线服务的 Service-Level Objective (SLO) 和高吞吐量,我们采用以下部署策略,将预填充和解码阶段分离

3.4.1. 预填充

预填充阶段的最小部署单元由 4 个节点组成,每个节点配备 32 个 GPU。注意力部分采用 4 路张量并行(TP4)与序列并行(SP),结合 8 路数据并行(DP8)。其小的 TP 尺寸为 4,限制了 TP 通信的开销。对于 MoE 部分,我们使用 32 路专家并行(EP32),确保每个专家处理足够大的批量大小,从而提高计算效率。

对于 MoE 全连接通信,我们使用与训练中相同的方法:首先通过 IB 在节点之间传输 token,然后通过 NVLink 在节点内 GPU 之间转发。特别是,我们在浅层的密集 MLP 中使用 1 路张量并行,以节省 TP 通信。

为了在 MoE 部分的不同专家之间实现负载平衡,我们需要确保每个 GPU 处理大致相同数量的令牌。为此,我们引入了冗余专家(redundant experts)的部署策略,即复制高负载专家进行冗余部署。高负载专家是基于在线部署期间收集的统计数据检测的,并定期调整。

此外,在预填充阶段,为了提高吞吐量并隐藏全互连和 TP 通信的开销,我们同时处理两个具有相似计算工作量的微批次,将一个微批次的注意力和 MoE 操作与另一个微批次的 dispatch 和 combine 操作重叠进行。

3.4.2. 解码

在解码过程中,我们将共享专家视为一个路由专家。从这个角度来看,每个 token 在路由过程中会选择 9 个专家,其中共享专家被视为一个总是会被选择的负载较重的专家。解码阶段的最小部署单元由 40 个节点组成,每个节点配备 320 个 GPU。注意力部分采用 TP4 和 SP 结合 DP80,而 MoE 部分使用 EP320。在 MoE 部分,每个 GPU 只托管一个专家,64 个 GPU 负责托管冗余专家和共享专家。Dispatch 和 combine 部分的全局通信通过 IB 上的直接点对点传输来实现低延迟。此外,我们还利用 IBGDA 技术进一步最小化延迟并提高通信效率。

类似于预填充,我们根据在线服务的统计专家负载定期确定某个间隔内的冗余专家集合。然而,由于每个 GPU 只托管一个专家,我们不需要重新排列专家。

4. 预训练

4.1. 数据构建

与 DeepSeek-V2 相比,我们通过增加数学和编程样本的比例,同时扩展多语言覆盖范围来优化预训练语料库。此外,我们的数据处理流程经过精炼,以在保持语料库多样性的同时最小化冗余。受到 Ding 等人的启发,我们实施了文档打包(document packing)方法以确保数据完整性,但在训练期间不采用跨样本注意力掩码(cross-sample attention masking)。最终,DeepSeek-V3 的训练语料库包含 14.8 T高质量且多样化的 token。

在 DeepSeekCoder-V2 的训练过程中,我们观察到填充中间(Fill-in-Middle,FIM)策略不会妨碍下一个令牌的预测能力,同时使模型能够根据上下文线索准确预测中间文本。与 DeepSeekCoder-V2 一致,我们也在 DeepSeek-V3 的预训练中采用了 FIM 策略。具体来说,我们采用前缀-后缀-中间(Prefix-Suffix-Middle,PSM)框架来构建数据,如下所示:

\[\text{<|fim_begin|>} f_{pre} \text{<|fim_hole|>} f_{suf} \text{<|fim_end|>} f_{middle} \text{<|eos_token|>}\]

这种结构应用在文档级别,作为预打包过程的一部分。FIM 策略的应用率为0.1,与 PSM 框架保持一致。

DeepSeek-V3 的分词器采用字节级 BPE,扩展了 128K 令牌的词汇表。我们的分词器的前置分词器(pretokenizer)和训练数据经过修改,以优化多语言压缩效率。此外,与 DeepSeek-V2 相比,新的前置分词器引入了结合标点和换行符的 token。

4.3. Long Context Extension

我们采用了类似于 DeepSeek-V2 的方法,以实现 DeepSeek-V3 中的长上下文能力。在预训练阶段之后,我们应用了 YaRN 进行上下文扩展,并进行了两个额外的训练阶段,每个阶段包括 1000 个步骤,逐步将上下文窗口从 4K 扩展到 32K,然后再扩展到 128K。在第一个阶段中,序列长度设置为 32K,批量大小为 1920。在第二个阶段中,序列长度增加到 128K,批量大小减少到 480。两个阶段的学习率都设置为 $7.3 × 10^{−6}$,与预训练阶段的最终学习率相匹配。

5. 后训练

5.1 有监督微调

我们精心策划了指令调优数据集,包括 150 万个实例,涵盖多个领域,每个领域都采用了独特的数据创建方法,以满足其特定需求。

推理数据

对于与推理相关的数据集,包括数学、代码竞赛问题和逻辑谜题等,我们利用内部的 DeepSeek-R1 模型生成数据。具体而言,虽然 R1 生成的数据表现出很高的准确性,但存在过度思考、格式不佳和长度过长等问题。我们的目标是在保持 R1 生成的推理数据高准确性的同时,平衡常规格式化推理数据的清晰性和简洁性。

为了建立我们的方法论,我们首先开发了一个专门针对特定领域(如代码、数学或一般推理)的专家模型,使用结合监督微调(SFT)和强化学习(RL)的训练流程。这个专家模型作为最终模型的数据生成器。训练过程涉及为每个实例生成两种不同类型的 SFT 样本:第一种将问题与其原始回答耦合在一起,格式为<问题,原始回答>,而第二种则在问题和 R1 回答的基础上加入系统提示,格式为<系统提示,问题,R1回答>。

系统提示经过精心设计,包括指导模型产生具有反思和验证机制的回答的说明。在强化学习阶段,模型利用 high-temperature sampling 生成回答,将 R1 生成的数据和原始数据的模式融合在一起,即使没有明确的系统提示。经过数百个强化学习步骤后,中间的强化学习模型学会了整合 R1 的模式,从而策略性地提高整体性能。

在完成强化学习训练阶段后,我们采用拒绝抽样(rejection sampling)的方法为最终模型策划高质量的 SFT 数据,其中专家模型被用作数据生成源。这种方法确保了最终训练数据保留了 DeepSeek-R1 的优势,同时产生简洁而有效的回答。

非推理数据

对于非推理数据,例如创意写作、角色扮演和简单的问答,我们利用 DeepSeek-V2.5 生成回答,通过人工验证数据的准确性和正确性。

SFT设置

我们使用 SFT 数据集对 DeepSeek-V3-Base 进行两个 epoch 的微调,使用余弦衰减学习率调度,初始学习率为 $5×10^{−6}$,逐渐降低到 $1×10^{−6}$。在训练过程中,每个序列都是由多个样本组成的。 我们采用了样本屏蔽策略,确保这些样本保持独立相互不可见。

5.2. 强化学习

5.2.1. 奖励模型

我们采用了基于规则的奖励模型和基于模型的奖励模型。

基于规则的 RM

对于可以使用特定规则验证的问题,我们采用基于规则的奖励系统来确定反馈。例如,某些数学问题具有确定性结果,我们要求模型以指定的格式提供最终答案,以便我们可以应用规则来验证正确性。同样,对于 LeetCode 问题,我们可以利用编译器根据测试用例生成反馈。通过尽可能利用基于规则的验证,我们确保了更高的可靠性。

基于模型的 RM

对于具有自由形式的真实答案的问题,我们依靠奖励模型来确定回答是否与预期的真实答案相匹配。相反,对于没有明确真实答案的问题,例如涉及创意写作的问题,奖励模型负责根据问题和相应的答案提供反馈。奖励模型是从 DeepSeek-V3 的 SFT checkpoint 进行训练的。为了增强其可靠性,我们构建了偏好数据,不仅提供最终的奖励,还包括导致奖励的思路链。这种方法有助于减轻特定任务中奖励操纵的风险。

5.2.2. Group Relative Policy Optimization

类似于 DeepSeek-V2,我们采用了 Group Relative Policy Optimization(GRPO)。

在强化学习过程中,我们融入了来自不同领域的 prompt,例如编码、数学、写作、角色扮演和问题回答。这种方法不仅使模型更加符合人类的偏好,还提高了在基准测试中的性能,特别是在可用的 SFT 数据有限的情况下的场景中。

5.4. 讨论

5.4.1. 从 Deepseek-R1 蒸馏

我们的研究表明,从推理模型中进行知识蒸馏是一种有前途的后训练优化方向。虽然我们目前的工作重点是从数学和编码领域提炼数据,但这种方法在各种任务领域中都显示出潜力。在这些特定领域展示的有效性表明,长 CoT 知识蒸馏可能对于增强在需要复杂推理的其他认知任务中的模型性能是有价值的。对于在不同领域中进一步探索这种方法仍然是未来研究的一个重要方向。

5.4.2. Self-Rewarding

在强化学习中,奖励在引导优化过程中起着关键作用。在一些编码或数学场景等外部工具验证简单的领域中,强化学习展示了出色的效果。然而,在更一般的场景中,通过硬编码构建反馈机制是不切实际的。在开发 DeepSeek-V3 时,针对这些更广泛的情境,我们采用了 constitutional AI 方法,利用 DeepSeek-V3 自身的投票评估结果作为反馈来源。这种方法产生了显著的对齐效果,极大地提升了DeepSeek-V3在主观评估中的性能。通过整合额外的 constitutional 输入,DeepSeek-V3可以朝着 constitutional 方向进行优化。

5.4.3. Multi-Token Prediction Evaluation

DeepSeek-V3 通过 MTP 技术预测接下来的两个 token。结合推测解码框架可以显著加快模型的解码速度。根据我们的评估,第二个 token 预测的接受率在不同生成主题中介于 85% 到 90% 之间,体现出一致的可靠性。这个高接受率使得 DeepSeek-V3 能够实现显著提高的解码速度,达到 1.8 倍的 TPS(每秒生成的 token 数)。