训练预算:算力、时间与费用

用 GPU-hours 和短时试跑,将训练规模转化为可执行的预算。

通过 DeepSeek-V3 的公开案例,学习如何估算训练时间与费用。

假设我们准备训练一个模型,模型结构和训练数据量已经初步确定。那我们究竟如何确定到底需要花多少钱呢?

作为穷学生,一定要精打细算!

核心主要是以下两个问题:

  1. 时间:现有的 GPU 需要运行多久?
  2. 预算:完成这次训练需要多少钱?

这两个问题需要放在一起考虑。增加 GPU 通常可以缩短训练时间,但在单价和单卡效率相同的情况下,总费用并不会因此降低。实际需要多少预算,还要看训练任务消耗了多少 GPU-hours。 本篇以 DeepSeek-V3 为例,逐步完成这份预算。首先,我们计算总资源需求;其次,我们换算训练时间和费用;最后,我们用同样的方法,为自己的训练任务建立一张预算表。

具体任务示例#

DeepSeek-V3 的技术报告公开了模型规模、训练 token 数、硬件配置和 GPU-hours,适合用来说明预算的计算过程。
DeepSeek-V3 是 MoE 模型,每个 token 只使用其中一部分参数参与计算,因此报告同时给出了总参数量和激活参数量。DeepSeek-V3 技术报告

我们先关注它的预训练阶段。报告中的主要数据如下:

项目DeepSeek-V3 的公开数据
模型总参数量671 B
每个 token 的激活参数量37 B
预训练数据量14.8 T token
训练集群2048 张 H800
每训练 1T token 所需资源约 18 万 H800 GPU-hours

公开模型的训练加速器数
公开模型的训练加速器数

我们还需要知道这些卡运行了多久,才能计算训练消耗的资源。这里就要用到 GPU-hours。

一张 GPU 运行一小时,消耗的资源是 1 GPU-hour。100 张 GPU 同时运行一小时,消耗的资源是 100 GPU-hours。

因此:

GPU-hours=Number of GPUs×Running Hours\text{GPU-hours}=\text{Number of GPUs}\times\text{Running Hours}

这个单位把 GPU 数量和运行时间合并起来,便于比较训练任务消耗了多少计算资源,也便于计算费用。

接下来,我们根据表中的数据,依次计算这次预训练需要多少 GPU-hours、多少天和多少费用。

第一步:计算 GPU-hours#

DeepSeek-V3 每训练 1T token,大约需要 18 万 H800 GPU-hours。预训练计划处理 14.8T token,因此:

预训练 GPU-hours=训练数据量×单位数据量的资源消耗=14.8×180,000=2,664,000\begin{aligned} \text{预训练 GPU-hours} &=\text{训练数据量}\times\text{单位数据量的资源消耗}\\ &=14.8\times180{,}000\\ &=2{,}664{,}000 \end{aligned}

也就是 266.4 万 GPU-hours。

这一步可以理解为计算一项工程的总工作量。
如果保持相同的模型、训练配置和运行效率,那么训练数据量增加一倍,GPU-hours 也大致增加一倍。这使我们可以先测量一段较短的训练,再估算完整任务的资源需求。

公开模型的训练 GPU-hours 与模型规模
公开模型的训练 GPU-hours 与模型规模

第二步:GPU-hours 换算成训练天数#

前面,我们已经算出总资源需求是 266.4 万 GPU-hours。接下来,我们把这些工作量分配给 2048 张 GPU,所需时间为:

训练小时数=GPU-hoursGPU 数量=2,664,0002048≈1300.8 小时\begin{aligned} \text{训练小时数} &=\frac{\text{GPU-hours}}{\text{GPU 数量}}\\ \\ &=\frac{2{,}664{,}000}{2048}\\ &\approx1300.8\text{ 小时} \end{aligned}

换算成天:

训练天数=1300.824≈54.2 天\text{训练天数} =\frac{1300.8}{24} \approx54.2\text{ 天}

因此,按照这个资源消耗水平,2048 张 H800 完成预训练约需 54 天。 假设集群扩展后,每张 GPU 的平均训练效率保持不变,就可以得到以下结果:

GPU 数量总 GPU-hours预计训练时间
1024 张266.4 万约 108.4 天
2048 张266.4 万约 54.2 天
4096 张266.4 万约 27.1 天

这张表展示了理想的线性扩展关系:GPU 数量增加一倍,时间缩短一半,总 GPU-hours 保持相同。

实际训练中,增加 GPU 会改变通信开销、并行方式和设备利用情况。因此,我们在规划新的集群规模时,还需要测量对应配置下的训练速度,再更新这张表。

DeepSeek-V3 预训练时间随 GPU 数量变化
DeepSeek-V3 预训练时间随 GPU 数量变化

因此,GPU 数量决定了可以投入多少并行资源,实际吞吐决定了这些资源能够多快完成训练。

第三步:根据单价计算费用#

知道总 GPU-hours 和训练时间后,我们就可以继续计算费用。假设 H800 的计费单价为每张每小时 2 美元,则:

预训练费用=GPU-hours×GPU 小时单价=2,664,000×2=5,328,000 美元\begin{aligned} \text{预训练费用} &=\text{GPU-hours}\times\text{GPU 小时单价}\\ &=2{,}664{,}000\times2\\ &=5{,}328{,}000\text{ 美元} \end{aligned}

即 532.8 万美元。

DeepSeek-V3 技术报告也采用了每 GPU-hour 2 美元的假设,并分别列出了各训练阶段的资源消耗和费用:

阶段H800 GPU-hours按 2 美元/GPU-hour 折算的费用
预训练266.4 万532.8 万美元
上下文扩展11.9 万23.8 万美元
后训练0.5 万1 万美元
合计278.8 万557.6 万美元

报告说明,这一费用口径覆盖正式训练,前期研究和消融实验的成本另计。这里的 2 美元也是报告采用的折算假设,我们在做实际预算时,需要代入自己的合同价格或内部核算价格。DeepSeek-V3 技术报告

至此,我们已经完成了一次最基础的预算计算:

训练数据量⟶GPU-hours⟶训练时间与费用\boxed{ \text{训练数据量} \longrightarrow \text{GPU-hours} \longrightarrow \text{训练时间与费用} }

为自己的模型建立同样的预算#

DeepSeek-V3 的案例提供了单位 token 的资源消耗。对于自己的训练任务,我们也可以通过一次短时试跑,测出这个数值。

实际操作时,我们使用整个训练任务每秒处理的 token 数会更加直接。 这个数值称为训练吞吐,单位为 token/s。

设计划训练的 token 总量为 DD,整个集群的实测吞吐为 qq,那么:

训练秒数=Dq\text{训练秒数}=\frac{D}{q}

再将秒换算成小时:

训练小时数=Dq×3600\text{训练小时数}=\frac{D}{q\times3600}

最后计算:

GPU-hours=GPU 数量×训练小时数\text{GPU-hours}=\text{GPU 数量}\times\text{训练小时数} 训练费用=GPU-hours×GPU 小时单价\text{训练费用}=\text{GPU-hours}\times\text{GPU 小时单价}

5.1 如何测量训练吞吐?#

如果训练日志已经记录整个任务的 token/s,我们可以直接使用稳定运行阶段的统计结果。

如果日志只记录每一步耗时,我们就可以根据每步处理的 token 数计算吞吐:

训练吞吐=每步处理的 token 数平均步时\text{训练吞吐} =\frac{\text{每步处理的 token 数}}{\text{平均步时}}

在固定序列长度、充分打包的情况下:

每步 token 数=全局 batch size×序列长度\text{每步 token 数} =\text{全局 batch size}\times\text{序列长度}

例如,全局 batch size 为 32,序列长度为 2048,则每一步处理:

32×2048=65,536 token32\times2048=65{,}536\text{ token}

如果平均每步需要 2 秒,整个训练任务的吞吐就是:

q=65,5362=32,768 token/sq=\frac{65{,}536}{2} =32{,}768\text{ token/s}

这里的“全局 batch size”表示整个任务完成一次优化器更新所处理的序列数量。在常见的数据并行配置中:

全局 batch size=每卡 micro batch size×梯度累积次数×数据并行度\text{全局 batch size} = \text{每卡 micro batch size} \times \text{梯度累积次数} \times \text{数据并行度}

采用变长序列或存在较多 padding 时,我们还需要明确吞吐统计的是有效 token 还是包含 padding 的 token,并与预算中的数据量保持相同口径。

5.2 用试跑结果估算完整训练#

继续使用上面的吞吐。假设计划训练 12B token,则:

训练小时数=12×10932,768×3600≈101.7 小时\text{训练小时数} = \frac{12\times10^9}{32{,}768\times3600} \approx101.7\text{ 小时}

假设这次试跑使用 8 张 GPU,则:

GPU-hours=8×12×10932,768×3600≈813.8\text{GPU-hours}=\frac{8\times12\times10^9}{32{,}768\times3600}\approx813.8

如果单价为 2 美元/GPU-hour,费用约为:

训练费用=813.8×2≈1627.6 美元\text{训练费用}=813.8\times2\approx1627.6\text{ 美元}

应用到自己的任务时,我们需要替换训练数据量、实测吞吐、GPU 数量和单价。 后续的估算方法会结合本仓库的实测结果,演示这一过程。

从理想估算到可执行预算#

前面的计算给出了持续训练所需的时间。正式排期还需要考虑检查点保存、评测、维护和故障恢复等开销。

我们可以先把这些开销分成两部分:

开销如何纳入预算
固定频率的评测、检查点保存根据单次耗时和执行次数,单独累计
维护、故障和恢复造成的损耗根据历史记录估算,或设置不同情景

如果保存和评测已经包含在测量吞吐的时间窗口中,我们在预算时就需要沿用这一口径,避免重复计入。

6.1 为训练时间设置一个范围#

回到 DeepSeek-V3 的预训练算例。前面计算得到的基准时间约为 54.2 天。

为了演示排期,假设在这一基准之外,计划集群还有额外的维护和故障损耗。用“有效训练时间占预留时间的比例”表示可用率,则:

预留时间=基准训练时间可用率\text{预留时间} = \frac{\text{基准训练时间}}{\text{可用率}}

我们可以建立三个规划情景:

规划情景假设可用率预留时间
按基准运行100%约 54.2 天
存在少量额外损耗95%约 57.1 天
存在较多额外损耗90%约 60.2 天

实际项目可以根据同一集群的历史运行记录替换它们。如果 GPU 在整个预留期间持续计费,预留时间增加也会带来费用增加。若按其他方式计费,应按相应合同口径核算。

6.2 启动前检查方案能否落地#

完成时间和费用估算后,我们还需要检查三个条件:

  • 显存是否足够。 首先,我们需要在试跑中完成完整训练步骤,并观察峰值显存;模型参数、梯度、优化器状态、激活和通信缓冲区都会占用空间。
  • 数据是否能够按计划供给。 其次,我们需要确认清洗、分词后的可用 token 数,明确重复训练的次数,并检查数据读取能否跟上训练速度。
  • 训练质量是否达到预期。 最后,我们需要在预算表中附上验证 loss 或任务指标的验收方式,便于判断这笔投入最终完成了什么目标。

这些检查决定了当前方案是否可以进入正式训练。调整模型、序列长度或并行配置后,需要重新测量吞吐并更新预算。

模型规模和 token 数如何确定?#

上面的案例先给定模型和 token 数,计算完成训练需要多少资源。实际规划还需要决定:应该训练多大的模型,以及给它多少数据。

前面我们检查了训练质量是否达到预期,这一步则需要进一步考虑:在同样的预算下,怎样分配模型规模和数据量,才能得到更好的效果?

在相同的资源预算下,可以选择较大的模型、较少的训练 token,也可以选择较小的模型、较多的训练 token。不同组合的训练速度和最终效果会有差异。

公开模型的模型规模与训练 token 数
公开模型的模型规模与训练 token 数

因此,我们可以先准备少量候选方案,再逐一比较:

候选方案需要估计的内容
较小模型,训练更多 token训练时间、费用、质量和后续推理成本
较大模型,训练较少 token训练时间、费用、质量和显存需求
中间规模是否在质量、时间和费用之间取得更合适的平衡

Scaling law 可以帮助建立模型规模、数据量与验证 loss 之间的预测关系。结合小规模实验,就可以筛选值得继续投入的候选配置。

对于教程中的第一次预算练习,我们可以先选择一个已经确定的模型和 token 目标,完成吞吐测量与费用估算。掌握这个过程后,我们再进一步比较模型与数据的不同组合。

联系杜子源源