大模型预训练【模型大小】和【数据量】以及【训练成本】如何预估
本文摘要
本文围绕大模型的 Scaling Law(缩放定律)展开,主要内容如下:
- Scaling Law 基础:介绍其本质是预测模型性能与参数量、数据量、计算量关系的“公式”,给出经典公式,并解释各参数含义。
- 实验与参数推算:设计包含不同模型参数量和数据量组合的实验矩阵,收集 Loss 等数据,通过最小二乘法拟合公式参数,进而推算大模型(如 70B 模型)的最优配置(数据量、Loss 等),还涉及学习率等相关参数的推算。
- Loss 与 Benchmark 关联:建立 Loss 到 Benchmark(如 MMLU、HumanEval 等)映射关系的原因,即传统 Scaling Law 仅能预测 Loss,而实际更关心模型在各类任务上的表现;介绍核心思路是构建从 Loss 到 Benchmark 分数的函数关系,并通过多模型多阶段训练保存 checkpoint、收集数据来拟合该关系,从而实现对大模型实际任务性能的预测。
- 实际案例:以 GPT - 3 为例,说明其训练时先从小模型实验中发现参数量与 Loss 的关系,进而推算大模型(175B)的训练量和性能,且最终 GPT - 3 175B 的训练量符合当时 Scaling Law 预测。
预估公式
老板问“7 B 模型、300 B token、128 张 A100显卡” 大约 多少天 能训完。 知道 N(模型参数量)、D(训练数据量) 能秒算几张 A100 跑多少天。
Scaling-Law 并不是一条“唯一”的公式,而是一组经验幂律(power-law)关系式,用来刻画大语言模型(LLM)的最终损失 L(或任意指标 P)随模型参数量 N、训练数据量 D 和计算预算 C 的变化趋势。最常被引用、也最容易落地的两条形式如下:
-
OpenAI 2020 形式(拟合损失)
L(N,D) = E + A/N^α + B/D^β- E:不可约损失(数据熵下界)
- A,B,α,β:拟合常数
用途:给定 N 和 D,可直接预估训练完成后的交叉熵损失。
-
Chinchilla(DeepMind 2022)形式(算力最优)
C ≈ 6ND
L(N,D,C) = E + A/N^α + B/D^β (或等价写成 P = aN^α D^β C^γ)
用途:在固定训练算力 C 下,求使损失最小的 (N,D) 组合,即“算力最优”分配方案——这就是著名的 Chinchilla 最优律:N_opt ∝ D_opt ∝ C^1/2。
主要作用
- 预测:用小模型/小数据实验拟合幂律,外推大模型损失或指标,避免一次性烧大钱训大模型。
- 资源分配:在训练预算有限时,按 Scaling-Law 算出“最优”参数量与数据量的比例,使损失最低。
- 极限分析:估计继续放大 N、D、C 的收益何时进入边际递减,判断“Scaling 撞墙”点。
简言之,Scaling-Law 就是大模型领域的“性能-资源换算表”,让研究者先在小规模实验里“算清楚”,再决定是否大规模投入训练。
Scaling Law 展开讲解
基于 Scaling Law 公式的参数推算
一、什么是 Scaling Law?
Scaling Law 本质上就是一个“预测公式”,它告诉我们模型性能与三个关键因素的关系:
- N(模型参数量):模型有多少个参数
- D(数据量):用了多少 token 来训练
- C(计算量):总共用了多少算力
二、核心公式
最经典的 Scaling Law 公式是:

其中:
- L = 模型的 loss 值
- A, B, E = 常数(需要通过实验拟合)
- α, β = 缩放指数(通常 α≈0.076,β≈0.095)
具体实验步骤
步骤1: 设计实验矩阵
假设我们要推算一个 70B 模型的最优配置,先训练一系列小模型:
步骤2: 收集 Loss 数据
运行所有实验,收集每个模型的最终 loss 值。比如得到这样的数据:
125M + 10B tokens → Loss = 3.2
125M + 20B tokens → Loss = 3.0
125M + 50B tokens → Loss = 2.8
…
2.7B + 100B tokens → Loss = 2.1
步骤3: 拟合公式参数
使用最小二乘法拟合出 A, B, E, α, β 这些参数。假设拟合结果是:
- A = 8.5
- B = 30.2
- E = 1.85
- α = 0.076
- β = 0.095
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
大模型scaling Law实验矩阵设计与参数拟合
通过训练小模型来预测大模型的最优配置
Scaling Law公式:Loss=A+B*N^(-α)+ E* D^(-β)
其中:
-N:模型参数数量(单位:百万)
-D:训练数据量(单位:十亿tokens)
-A,B,E,a,β:需要拟合的参数
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import minimize
from sklearn.metrics import r2_score
import itertools
class ScalingLawExperiment:
def __init__(self):
"""初始化实验类"""
self.experiment_data = None
self.fitted_params = None
def design_experiment_matrix(self, model_sizes=None, data_sizes=None):
"""
步骤1: 设计实验矩阵
生成模型大小和数据量的所有组合
"""
print("步骤1: 设计实验矩阵")
print("=" * 50)
# 默认的模型大小范围(单位:百万参数)
if model_sizes is None:
model_sizes = [10, 50, 100, 200, 500, 1000] # 10M ~ 1000M
# 默认的数据量范围(单位:十亿 tokens)
if data_sizes is None:
data_sizes = [10, 50, 100, 200, 500, 1000] # 10B ~ 1000B
experiments = []
exp_id = 1
# 生成所有模型大小和数据量的组合
for model_size, data_size in itertools.product(model_sizes, data_sizes):
experiments.append({
'exp_id': exp_id,
'model_size_M': model_size,
'data_size_B': data_size,
'status': 'planned'
})
exp_id += 1
self.experiment_matrix = pd.DataFrame(experiments)
print(f"设计了{len(experiments)} 个实验:")
print(f"模型大小范围: {min(model_sizes)}M - {max(model_sizes)}M 参数")
print(f"数据量范围: {min(data_sizes)}B - {max(data_sizes)}B tokens")
print("\n实验矩阵预览:")
print(self.experiment_matrix.head(10))
print(f"... (共{len(experiments)}个实验)")
return self.experiment_matrix
def simulate_loss_data(self, noise_level=0.1):
"""
步骤2: 模拟收集Loss数据
使用预设的真实参数生成模拟数据
"""
print("\n步骤2: 收集Loss数据(模拟实验结果)")
print("=" * 50)
# 真实的Scaling Law参数(用于生成模拟数据)
true_params = {
'A': 2.0, # 不可约损失
'B': 400.0, # 模型规模相关系数
'E': 50.0, # 数据量相关系数
'alpha': 0.076, # 模型规模指数
'beta': 0.095 # 数据量指数
}
def scaling_law(N, D, A, B, E, alpha, beta):
"""Scaling Law公式"""
return A + B * (N ** (-alpha)) + E * (D ** (-beta))
# 为每个实验生成Loss值
losses = []
for _, row in self.experiment_matrix.iterrows():
N = row['model_size_M'] # 模型大小(百万参数)
D = row['data_size_B'] # 数据量(十亿tokens)
# 计算理论Loss值
true_loss = scaling_law(N, D, **true_params)
# 添加噪声模拟真实实验的不确定性
noise = np.random.normal(0, noise_level)
observed_loss = true_loss + noise
losses.append(observed_loss)
self.experiment_matrix['loss'] = losses
self.experiment_matrix['status'] = 'completed'
# 显示一些示例结果
print("实验结果示例:")
sample_results = self.experiment_matrix.sample(10).sort_values('loss')
for _, row in sample_results.iterrows():
print(f"{row['model_size_M']:>4}M + {row['data_size_B']:>3} B tokens → Loss = {row['loss']:.3f}")
print(f"\n生成了{len(losses)} 个实验结果")
print(f"Loss范围: {min(losses):.3f} - {max(losses):.3f}")
return self.experiment_matrix
def fit_scaling_law_parameters(self):
"""
步骤3: 使用最小二乘法拟合Scaling Law参数
"""
print("\n步骤3: 拟合Scaling Law参数")
print("=" * 50)
# 提取数据
N = self.experiment_matrix['model_size_M'].values # 模型大小
D = self.experiment_matrix['data_size_B'].values # 数据量
L = self.experiment_matrix['loss'].values # 观测到的Loss
def objective_function(params):
"""目标函数: 最小化预测值与观测值的平方误差"""
A, B, E, alpha, beta = params
# 计算预测的Loss
predicted_loss = A + B * (N ** (-alpha)) + E * (D ** (-beta))
# 计算均方误差
mse = np.mean((predicted_loss - L) ** 2)
return mse
# 设置参数的初始猜测值和边界
initial_guess = [2.0, 400.0, 50.0, 0.1, 0.1]
bounds = [
(0.1, 10.0), # A: 不可约损失
(1.0, 1000.0), # B: 模型规模系数
(1.0, 1000.0), # E: 数据量系数
(0.01, 0.5), # alpha: 模型规模指数
(0.01, 0.5) # beta: 数据量指数
]
print("开始参数拟合...")
print(f"初始参数猜测: A={initial_guess[0]}, B={initial_guess[1]}, E={initial_guess[2]}, alpha={initial_guess[3]}, beta={initial_guess[4]}")
# 执行优化
result = minimize(
objective_function,
initial_guess,
method='L-BFGS-B',
bounds=bounds,
options={'disp': True}
)
if result.success:
A, B, E, alpha, beta = result.x
self.fitted_params = {
'A': A,
'B': B,
'E': E,
'alpha': alpha,
'beta': beta
}
print("\n拟合成功!")
print("拟合得到的参数:")
print(f"- A(不可约损失) = {A:.3f}")
print(f"- B(模型规模系数) = {B:.1f}")
print(f"- E(数据量系数) = {E:.1f}")
print(f"- α(模型规模指数) = {alpha:.3f}")
print(f"- β(数据量指数) = {beta:.3f}")
# 计算拟合质量
predicted = A + B * (N ** (-alpha)) + E * (D ** (-beta))
r2 = r2_score(L, predicted)
rmse = np.sqrt(np.mean((predicted - L) ** 2))
print(f"\n拟合质量:")
print(f"- R² = {r2:.4f}")
print(f"- RMSE = {rmse:.4f}")
return self.fitted_params
else:
print("拟合失败:", result.message)
return None
def predict_optimal_config(self, target_model_size, compute_budget_flops):
"""
步骤4: 使用拟合的参数预测最优配置
Args:
target_model_size: 目标模型大小(百万参数)
compute_budget_flops: 计算预算(FLOPs)
"""
if self.fitted_params is None:
print("错误: 请先执行参数拟合")
return None
print(f"\n步骤4: 预测 {target_model_size}M 参数模型的最优配置")
print("=" * 50)
A, B, E, alpha, beta = self.fitted_params.values()
# 简化假设: 给定模型大小, 找到最优的数据量
# 这里使用一个近似的计算预算约束
# 不同数据量下的预测Loss
data_sizes = np.logspace(1, 3, 50) # 10B到1000B tokens
predicted_losses = A + B * (target_model_size ** (-alpha)) + E * (data_sizes ** (-beta))
# 找到最优点(这里简化为Loss最小的点)
optimal_idx = np.argmin(predicted_losses)
optimal_data_size = data_sizes[optimal_idx]
optimal_loss = predicted_losses[optimal_idx]
print(f"对于 {target_model_size}M 参数的模型:")
print(f"- 推荐数据量: {optimal_data_size:.1f}B tokens")
print(f"- 预期最终Loss: {optimal_loss:.3f}")
# 也可以给出一些备选方案
print(f"\n不同数据量下的Loss预测:")
for d in [50, 100, 200, 500, 1000]:
loss = A + B * (target_model_size ** (-alpha)) + E * (d ** (-beta))
print(f"- {d:>4}B tokens → Loss = {loss:.3f}")
return {
'optimal_data_size': optimal_data_size,
'optimal_loss': optimal_loss,
'model_size': target_model_size
}
def visualize_results(self):
"""可视化实验结果和拟合曲线"""
if self.fitted_params is None:
print("错误: 请先执行参数拟合")
return None
print("\n步骤5: 可视化结果")
print("=" * 50)
# 提取数据
N = self.experiment_matrix['model_size_M'].values
D = self.experiment_matrix['data_size_B'].values
L = self.experiment_matrix['loss'].values
A, B, E, alpha, beta = self.fitted_params.values()
# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
# 图1: 模型大小 vs Loss (固定数据量为中位数)
median_D = np.median(D)
D_filtered = D == median_D
N_filtered = N[D_filtered]
L_filtered = L[D_filtered]
# 拟合曲线
N_range = np.logspace(np.log10(min(N)), np.log10(max(N)), 100)
L_fit_D = A + B * (N_range ** (-alpha)) + E * (median_D ** (-beta))
ax1.scatter(N_filtered, L_filtered, label=f'实验数据 (D={median_D}B)')
ax1.plot(N_range, L_fit_D, 'r-', label='拟合曲线')
ax1.set_xscale('log')
ax1.set_xlabel('模型大小 (M 参数)')
ax1.set_ylabel('Loss')
ax1.set_title(f'模型大小对Loss的影响 (固定数据量={median_D}B)')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 图2: 数据量 vs Loss (固定模型大小为中位数)
median_N = np.median(N)
N_filtered = N == median_N
D_filtered = D[N_filtered]
L_filtered = L[N_filtered]
# 拟合曲线
D_range = np.logspace(np.log10(min(D)), np.log10(max(D)), 100)
L_fit_N = A + B * (median_N ** (-alpha)) + E * (D_range ** (-beta))
ax2.scatter(D_filtered, L_filtered, label=f'实验数据 (N={median_N}M)')
ax2.plot(D_range, L_fit_N, 'r-', label='拟合曲线')
ax2.set_xscale('log')
ax2.set_xlabel('数据量 (B tokens)')
ax2.set_ylabel('Loss')
ax2.set_title(f'数据量对Loss的影响 (固定模型大小={median_N}M)')
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
def main():
"""主函数: 执行完整的Scaling Law实验流程"""
print("大模型Scaling Law实验矩阵设计与参数拟合")
print("=" * 60)
# 初始化实验
experiment = ScalingLawExperiment()
# 执行完整流程
experiment.design_experiment_matrix()
experiment.simulate_loss_data()
fitted_params = experiment.fit_scaling_law_parameters()
if fitted_params:
# 预测70B模型的最优配置
experiment.predict_optimal_config(
target_model_size=70000, # 70B = 70,000M 参数
compute_budget_flops=1e23 # 示例计算预算
)
# 可视化结果
try:
experiment.visualize_results()
except Exception as e:
print(f"可视化出错: {e}")
print("\n实验完成!")
if __name__ == "__main__":
main()
步骤4:推算大模型参数
现在我们要推算 70B 模型的最优配置。根据 Chinchilla 论文的结论,最优的数据量与模型大小比例约为 20:1,即:
最优训练 token 量 = 20×模型参数量
对于 70B 模型:
- 最优训练量 = 20 × 70B = 1.4T tokens
使用拟合的公式预测 loss:
L(70B, 1.4T) = 8.5/(70×10^9)^0.076 + 30.2/(1.4×10^12)^0.095 + 1.85
≈ 0.45 + 0.52 + 1.85
≈ 2.82
步骤5:学习率推算
学习率的 scaling law 通常遵循:
最优学习率 ∝ sqrt(batch_size) / sqrt(模型参数量)
如果我们知道 1.3B 模型在 batch_size=512 时最优学习率是 1e-4,那么 70B 模型:
lr_70B = 1e-4 × sqrt(新batch_size/512) × sqrt(1.3B/70B)
假设用相同的 batch_size=512:
lr_70B = 1e-4 × sqrt(1.3/70) ≈ 1e-4 × 0.136 ≈ 1.36e-5
实际案例:GPT - 3 的参数选择
OpenAI 在训练 GPT - 3 时就是这样做的:
- 先训练了 125M,350M,760M,1.3B 等小模型
- 发现参数量每增加 10x,loss 大约下降 0.35
- 据此推算 175B 模型需要的训练量和预期性能
- 最终 GPT - 3 175B 用了 300B tokens,基本符合当时的 scaling law 预测
Loss 到 Benchmark 的 Scaling Law
为什么要建立这个关系?
传统的 scaling law 只能预测 loss,但我们真正关心的是:
- 这个模型在 MMLU 上能考多少分?
- 在 HumanEval 代码测试上能达到什么水平?
- 需要训练多久才能在某个任务上达到 GPT - 4 的水平?
核心思路
建立从 loss 到实际能力的映射关系:
Benchmark_Score = f(Loss) = a × Loss^b + c
或者更复杂的:
Benchmark_Score = a × log(Loss) + b × sqrt(Loss) + c
具体实验步骤
步骤1:设计实验
训练一系列不同大小的模型,在不同训练阶段都保存 checkpoint:
模型配置:
- 125M:保存在 5B,10B,20B,50B,100B tokens 的 checkpoint
- 350M:同样保存 5 个 checkpoint
- 1.3B:同样保存 5 个 checkpoint
- 2.7B:同样保存 5 个 checkpoint
总共 20 个不同的模型状态
步骤2:收集双重数据
对每个 checkpoint 都测试:
- Training Loss(在验证集上)
- Benchmark 分数(如 MMLU, HellaSwag, HumanEval 等)
得到类似这样的数据点:
| 模型大小 | 训练Tokens | Training Loss | Perplexity | MMLU | HellaSwag | HumanEval | GSM8K | 训练时间(h) |
|---|---|---|---|---|---|---|---|---|
| 125M | 5B | 3.45 | 31.5 | 25.3 | 31.2 | 8.5 | 12.1 | 24 |
| 125M | 10B | 3.12 | 22.6 | 28.7 | 35.8 | 12.3 | 16.4 | 48 |
| 125M | 20B | 2.89 | 18.1 | 32.1 | 40.2 | 15.7 | 21.3 | 96 |
| 125M | 50B | 2.71 | 15 | 35.8 | 44.6 | 19.2 | 26.8 | 240 |
| 125M | 100B | 2.58 | 13.2 | 38.4 | 47.3 | 22.1 | 30.5 | 480 |
| 350M | 5B | 2.98 | 19.7 | 32.1 | 42.5 | 16.8 | 22.4 | 48 |
| 350M | 10B | 2.67 | 14.4 | 36.9 | 48.2 | 23.5 | 29.7 | 96 |
| 350M | 20B | 2.43 | 11.4 | 41.3 | 52.8 | 28.9 | 36.2 | 192 |
| 350M | 50B | 2.24 | 9.4 | 46.7 | 58.1 | 34.6 | 42.8 | 480 |
| 350M | 100B | 2.11 | 8.2 | 50.2 | 61.4 | 38.7 | 47.3 | 960 |
| 1.3B | 5B | 2.54 | 12.7 | 42.8 | 55.3 | 28.4 | 35.6 | 120 |
| 1.3B | 10B | 2.21 | 9.1 | 48.5 | 62.7 | 36.9 | 44.2 | 240 |
| 1.3B | 20B | 1.96 | 7.1 | 54.2 | 68.4 | 43.7 | 52.8 | 480 |
| 1.3B | 50B | 1.78 | 5.9 | 60.8 | 74.2 | 51.3 | 61.4 | 1200 |
| 1.3B | 100B | 1.65 | 5.2 | 65.7 | 78.1 | 56.8 | 67.9 | 2400 |
| 2.7B | 5B | 2.31 | 10.1 | 48.2 | 61.8 | 34.7 | 42.3 | 200 |
| 2.7B | 10B | 1.98 | 7.2 | 55.9 | 69.5 | 44.1 | 52.6 | 400 |
| 2.7B | 20B | 1.73 | 5.6 | 62.4 | 75.8 | 52.9 | 62.1 | 800 |
| 2.7B | 50B | 1.54 | 4.7 | 69.7 | 81.3 | 61.8 | 71.4 | 2000 |
| 2.7B | 100B | 1.42 | 4.1 | 74.2 | 84.6 | 67.3 | 76.8 | 4000 |
步骤3:拟合映射关系
使用回归分析找出最佳拟合曲线。以 MMLU 为例:
#伪代码示例
import numpy as np
from scipy.optimize import curve_fit
def mmlu_scaling_law(loss, a, b, c):
return a * np.power(loss, b) + c
# 拟合参数
losses = [3.45, 3.21, 2.98, ..., 2.15]
mmlu_scores = [25.2, 26.1, 27.8, ..., 45.6]
params, _ = curve_fit(mmlu_scaling_law, losses, mmlu_scores)
a, b, c = params
# 假设拟合结果: a=-15.2, b=-1.3, c=75.8
得到公式:
MMLU_Score = -15.2 × Loss^(-1.3) + 75.8
步骤4:验证和预测
现在可以预测大模型的性能了!
比如我们之前算出 70B 模型预期 loss=2.82,那么:
MMLU_Score = -15.2 × (2.82)^(-1.3) + 75.8
≈ -15.2 × 0.28 + 75.8
≈ 71.5%
这意味着 70B 模型训练到 1.4T tokens 时,预期在 MMLU 上能达到 71.5% 的分数。
步骤5:训练计划制定
基于这个预测,我们可以制定训练计划:
训练目标:MMLU 达到 75%
根据公式反推:
75 = -15.2 × Loss^(-1.3) + 75.8
Loss ≈ 2.65
再根据 scaling law 反推需要的训练量:
2.65 = 8.5/(70×109)0.076 + 30.2/D^0.095 + 1.85
D ≈ 2.1T tokens
结论:需要训练约 2.1T tokens 才能在 MMLU 上达到 75%
实际案例:DeepSeek 的做法
DeepSeek-V2 技术报告中展示了类似的做法:
- 多任务拟合:他们建立了从 loss 到多个 benchmark 的映射关系
- 能力预测:在模型训练到一半时就能预测最终性能
- 训练优化:发现某些任务提升缓慢时,会调整数据配比
- 停止条件:当预测显示继续训练收益递减时,提前停止
例如他们发现:
- 数学能力的提升需要 loss 降到特定阈值以下
- 代码能力与 loss 呈现非线性关系
- 多语言能力在某个 loss 值附近会有“突破点”
实用技巧
- 多样本验证:不要只用一条曲线,要用多个独立实验验证
- 任务特异性:不同 benchmark 的拟合公式可能完全不同
- 动态调整:在大模型训练过程中,定期验证预测准确性
- 安全冗余:预测基础上增加 20-30% 的训练冗余
通过这种方法,你可以在投入大量算力训练大模型之前,就对最终效果有相对准确的预期,避免“训练盲目”的问题。
演示 Scaling-Law
用一组“小实验”来演示 Scaling-Law 怎么用,把抽象公式变成能看懂的数字。
1. 先在小模型上做 4 组实验
(全部训练到收敛,记录验证集交叉熵损失)
| 实验 | 参数量 N | 数据量 D | 计算量 C≈6ND | 实测损失 L |
|---|---|---|---|---|
| ① | 50 M | 2 B | 6×10¹⁴ FLOP | 3.20 |
| ② | 100 M | 2 B | 1.2×10¹⁵ | 2.98 |
| ③ | 100 M | 8 B | 4.8×10¹⁵ | 2.76 |
| ④ | 200 M | 8 B | 9.6×10¹⁵ | 2.58 |
把 4 个点拿去拟合 OpenAI 2020 形式
L(N,D)=E + A/N^α + B/D^β
就能解出(示意值)
E=2.10,A=0.80,α=0.34,B=0.25,β=0.28
2. 现在老板问:
“我想把损失降到 2.30,大概需要多大模型、多少数据?”
把 L=2.30 代入公式,得到一条“等损失”曲线:
0.20 = 0.80/N^0.34 + 0.25/D^0.28
任选 N 就能解出对应 D,例如
- N=400 M ⇒ D≈18 B token
- N=1 B ⇒ D≈9 B token
- N=10 B ⇒ D≈2 B token
3. 再进一步:训练预算只有 3×10¹⁸ FLOP,怎么配比最划算?
用 Chinchilla 最优律:
C = 6ND = 3×10¹⁸
N_opt = (C/6)^(1/2) · k₁ ≈ 1.4 B
D_opt = (C/6)^(1/2) · k₂ ≈ 360 B
结论:
14 亿参数 + 3600 亿 token 能在 3×10¹⁸ FLOP 预算下把损失压到最低;
如果继续加大参数到 10 B,而数据只有 50 B,反而更费算力且损失更高——这就是“算力最优”配比要告诉你的事。
4. 一句话总结
Scaling-Law 让你用 4 次小规模实验(几十万美元)就能算出:
“要降到 2.30 损失,得 1 B 模型 + 9 B 数据,训练费约 5×10¹⁷ FLOP”,
而不用真的去烧一次千万美元的大训练。
计算量 C≈6ND
C≈6ND 是训练 Transformer 类语言模型时,最常用的一条“粗略估算总计算量”的经验公式。
它把三件事乘在一起:
- N:模型参数量(单位:个)
- D:训练时实际见过的 token 数(单位:个)
- 6:经验常数,表示每个 token、每个参数平均要做 6 次浮点运算(FLOP)
为什么正好是 6?
对 Decoder-only 的因果语言模型(GPT 系列),一次前向传播里:
- 权值计算(矩阵乘法)
每个参数贡献 2 FLOP(乘 + 加)。 - 反向传播求梯度
需要再算一遍,所以再贡献 2 FLOP。 - 参数更新(优化器 step)
每个参数还要 ≈2 FLOP(动量、Adam 更新等)。
加在一起 ≈ 6 FLOP / 参数 / token。
于是
总计算量 C ≈ 6 × N × D(单位:FLOP)
举个即时数字
- 模型:7 B 参数
- 数据:2 T token(2×10¹²)
C ≈ 6 × 7×10⁹ × 2×10¹²
≈ 8.4×10²² FLOP
≈ 84 ZFLOP(zetta,十万亿亿次)
用途
- 快速换算:知道 N、D 就能秒算“大概要多少张 A100 跑多少天”。
- 预算评估:老板给 10²¹ FLOP,你可以反推
- 如果固定 7 B 参数,只能训 24 B token;
- 如果想训 300 B token,模型最大只能 560 M。
- Scaling-Law 拟合:所有论文里把“C”当成横坐标画损失曲线,用的就是这条 6ND。
一句话:6ND 是把“模型大小”和“数据长度”翻译成“电费”的最简汇率。
把“多少 FLOP” 换算成 “几张 A100 + 多少天” 只需要再知道两个数:
-
A100 的理论算力
- FP16/BF16 稠密算力:312 TFLOP/s = 3.12×10¹⁴ FLOP/s
(1 张 A100,标称峰值)
- FP16/BF16 稠密算力:312 TFLOP/s = 3.12×10¹⁴ FLOP/s
-
实际利用率
大模型训练一般只能打到 30 %~50 % 的峰值,取 40 % 做估算:
有效算力 = 3.12×10¹⁴ × 0.4 ≈ 1.2×10¹⁴ FLOP/s 每张卡
秒算模板
| 步骤 | 公式 | 数值示例 |
|---|---|---|
| ① 算总计算量 | C = 6ND | 7 B 参数 × 300 B token → C=1.26×10²² FLOP |
| ② 单卡秒算力 | η×312 TFLOP | 40 %×312≈1.2×10¹⁴ FLOP/s |
| ③ 总秒数 | T = C/(卡数×单卡算力) | 128 张 A100:T=1.26×10²²/(128×1.2×10¹⁴)≈8.2×10⁵ s |
| ④ 换成天 | /86400 | ≈9.5 天 |
一句话结论
“7 B 模型、300 B token、128 张 A100” 大约 9~10 天 就能训完。
想再快一倍?加卡到 256 张,时间减半;预算只有 64 张?那就约 19 天。
更多推荐



所有评论(0)