首页优化地图方法索引基础概念
返回技术汇总表 ↗

M011 · 独立详解

输出投影与Loss内存优化:不把整张词表分数留在显存里

区分推理需要哪些位置的logits,以及训练如何分块计算完整交叉熵;分母、标签与反向都不能省错。

算子与编译内存与数据搬运详解已编写
视频讲解待制作

这篇文章的小视频尚未制作;可以先阅读下方文字详解。

本页目录

01 · 模型最后一层为什么也能占很多内存

Transformer产生隐藏向量H[T,D],输出权重W[V,D]把每个位置映射到V个词表分数:Z=H Wᵀ,形状[T,V]。logit是未经过Softmax的分数;交叉熵再用目标token和整行分数计算Loss。T可表示展平后的batch×序列位置。

自设T=4096、V=128000:FP16完整logits占1000 MiB,若另物化FP32副本则再占2000 MiB。Softmax、梯度、隐藏向量和权重尚未计入;实际是否同时驻留取决于实现,不把这些数字当某框架实测峰值。

依据:Cut Your Losses in Large-Vocabulary Language Models · 原始论文 ↗ · PyTorch · CrossEntropyLoss语义与reduction(main) ↗

02 · 推理:只给真正要采样的位置做投影

普通自回归Prefill后,通常只用每个请求最后有效位置的隐藏向量预测第一个生成token。若所有提示位置都做输出投影,会产生许多本次采样不需要的分数。可以先选这些行再做LM head;Transformer中间层仍需计算提示词。

教学示意 · 不代表硬件实测
普通单请求提示词:hidden shape [4096,D]
h_last = hidden[最后有效位置]
logits_next = h_last @ W.T      # [V]
# 不能误取padding最后一行;packed batch按请求边界选行。

本例单行FP16 logits约0.244 MiB,4096行完整表为1000 MiB。只减少LM head的行数和中间表,不代表整个Prefill加速4096倍。Decode一般本来就只有新位置,收益不能重复计算。

提示词logprob、困惑度、打分、投机验证、多位置预测等任务可能需要更多行;请求需要的分数必须保留。只选目标词也不能直接替代普通采样,因为top-k/top-p或Softmax归一化仍依赖其他候选。

依据:Apple · Cut Cross-Entropy原作者实现与数值路径(main) ↗

03 · 训练:Loss不是只看目标token的分数

先看无类别权重、无label smoothing的一行交叉熵:L=log(Σ_v exp(z_v))−z_y,其中y是正确目标。即使只输出一个标量Loss,分母仍依赖全部词表。

自设z=[0,ln2,ln3,ln4],目标y=2(从0编号)。目标概率3/10,Loss=ln(10)−ln(3)=ln(10/3)≈1.203973。只看目标分数,或者只在目标所在片段归一化,都会算错。

教学示意 · 不代表硬件实测
逐行稳定形式:
m = max(z)
L = m + log(sum(exp(z-m))) - z[target]
# 不必先生成并保存完整Softmax概率表。

依据:PyTorch · CrossEntropyLoss语义与reduction(main) ↗

04 · 两种分块:分token行,或分词表列

方法减少哪个中间表保留什么
按token行分块每次C×V logits,而非T×V每行仍遍历完整词表;累积Loss/梯度。
按词表列分块并融合每次小块投影并更新统计,避免全局完整logits全词表log-sum-exp与目标分数。
只融合已生成logits的交叉熵省部分Softmax/临时缓冲已有T×V logits仍存在,不能等同于融合Linear+Loss。

两种分块可以组合。把每块Loss相加后才统一按有效目标数归一化;不是每块取mean再无权平均。普通自动微分即使Python循环逐块前向,也可能把各块中间值都保留到统一backward,无法得到预想峰值,需要配套反向和生命周期设计。

同一个完整词表,临时表可以分多小?

T=4096,V=128000,每logit 2B;仅计一张临时logits表。小块处理后释放并保留必要统计,梯度/权重/隐藏向量等另计;本演示不模拟自动微分或设备内核。

演示只计一张FP16 logits临时表;不计输入、权重、统计和梯度,也不假设换分块后计算量变少。

依据:Cut Your Losses in Large-Vocabulary Language Models · 原始论文 ↗

05 · 不存完整词表,怎样算正确分母

为每行维护已见最大值m与指数和ℓ。新块最大值为mb时,mnew=max(m,mb);旧和乘exp(m−mnew),再加新块的Σexp(z−mnew)。最终log-sum-exp=m+logℓ。目标所在块顺便取出z_y。

教学示意 · 不代表硬件实测
m = -inf; ell = 0; target_logit = 未记录
for each vocabulary tile:
    z_tile = H_tile @ W_tile.T
    new_m = max(m, max(z_tile))
    ell = ell * exp(m-new_m) + sum(exp(z_tile-new_m))
    m = new_m
    若target在本块:记录对应z
loss = m + log(ell) - target_logit
# 第一块直接初始化,避免-inf-(-inf)。

上例按两列分块:块A=[0,ln2],局部指数总质量3;块B=[ln3,ln4],质量7。目标在B,正确分母仍为10,不能只用7;误算会得到ln(7/3)≈0.847298。机制与在线Softmax相通,但这里汇总的是词表归一化,不是Attention的Value输出。

依据:Cut Your Losses in Large-Vocabulary Language Models · 原始论文 ↗

06 · 反向仍需要完整词表的贡献

无权重标准交叉熵对logit的梯度是p_v−1[v=y],所以非目标类别通常也有梯度。给定保存的log-sum-exp,反向可重新生成当前logits块,算对应概率和梯度,再累积隐藏向量与分类权重梯度。

教学示意 · 不代表硬件实测
重算当前块z,p = exp(z - saved_logsumexp)
dZ = p - one_hot(target落在本块)
dZ *= Loss归一化及上游梯度
dH += dZ @ W_tile
dW_tile += dZ.T @ H
# dH跨词表块求和;dW按全部有效token累积。

这是用部分重算换取中间表容量,仍可能增加投影计算。Apple CCE实现还有梯度过滤等吞吐策略,应与“不物化完整logits”的内存思想分开:过滤微小梯度不等于保留所有梯度项。仓库提供关闭过滤的对照实现,实际支持和数值行为按安装版本核对。

依据:Apple · Cut Cross-Entropy原作者实现与数值路径(main) ↗

07 · 标签、忽略项和分布式分母不能改错

因果训练通常让位置i预测下一个token。先确定谁负责shift,避免数据预移一次、Loss接口又移一次。ignore_index表示该位置不贡献Loss;Packing和Padding的边界要沿用训练目标,不能因省logits而改成另一套标签。

本篇算例按有效目标数取mean。带类别权重、label smoothing、softcap、Z-loss或蒸馏全分布时,要实现相应定义,不能只套LSE−目标分数的最简公式。所有目标都被忽略时,分母为零,应明确训练框架的处理约定。

词表并行把列放在多个rank:先得到全局最大值,再求全局指数和和目标分数;dH也要按词表分片贡献归约。每卡对自己的词表算独立交叉熵再平均,无法得到完整词表Loss。

依据:PyTorch · CrossEntropyLoss语义与reduction(main) ↗ · Apple · Cut Cross-Entropy原作者实现与数值路径(main) ↗

08 · 小脚本同时核对Loss和梯度

下载脚本比较完整logits与按token/词表双向分块的交叉熵,覆盖非整除块、ignored目标和非均匀行块。输出dH、dW、bias梯度,并用有限差分验证;另展示只用目标词表块分母的错误结果。CPU没有自动微分保留问题,不测试设备峰值和速度。

教学示意 · 不代表硬件实测
先记录真实需求:采样行、打分行或训练标签
建立完整logits + 标准Loss基线
核对shift、mask、reduction、额外Loss项
运行融合/分块候选并验证前后向
测峰值显存、投影与重算、完整训练step
# 接口若不再返回logits,下游指标和调试流程也要适配。

CCE仓库是Linear+交叉熵融合的实现阅读入口,并提供词表并行和不同数值路径。不是所有loss函数、设备和模型包装都能直接替换。昇腾或其他后端应检查是否存在同定义的融合/分块实现,不能把一个CUDA包当跨平台开关。

依据:Apple · Cut Cross-Entropy原作者实现与数值路径(main) ↗ · vLLM Ascend · 支持功能矩阵(main) ↗

09 · 少占内存和更快,分别报告

检查重点
语义所需logits没有被省掉;Loss、标签、忽略项及全局归一化一致。
反向隐藏向量、分类权重与bias梯度;混合精度、过滤策略与数值误差。
内存完整/分块logits、重算缓冲、持久统计、梯度和实际峰值。
速度前向、反向、额外投影及调度总和;再看完整训练step或服务延迟。
  • 训练只监督一个目标token,为什么仍要遍历其他词表项?
  • 分块的mean为什么不能不加权平均?
  • FlashAttention和融合Linear+Loss都减少中间表,两者归一化的轴有什么不同?

流程位置与关联方法

这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。

资料与核查范围

原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-10。引用 main / latest 文档时,实际接口以安装版本为准。

代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。

← 返回总表中的 M011继续阅读:采样与约束解码实现优化 →
AI Infra 知识库 · 总览 → 独立讲解网站更新 2026-10-08
搜索知识库

搜索方法与基础概念 · Esc 关闭