想象你在一家人气爆棚的食堂打工。每位顾客进门,阿姨都要先去后厨把几十个装满食材的铝盆全部端出来,摆在台面上,然后才开始配菜。更要命的是——台面特别小,后厨到台面的通道又窄又慢,每服务完一位顾客,阿姨还得把所有盆子端回去,下一位顾客来,再全部端出来。你心里清楚:真正花时间的不是“做菜”,而是“搬盆”。 这正是经典注意力机制在大模型中的处境。它每处理一个词,都要把整个“注意力分数矩阵”(n×n)在显存中反复读写,序列稍微一长,显存立刻被塞满,训练直接卡死。Flash Attention 像一位聪明的食堂主管,它让阿姨改变规矩:不再把整个后厨搬到台面上,而是按顾客需求,把“当下要用的几盆菜”分批端到台前,用完一盆收一盆。仅凭这个“分批搬运”的朴素思路,Flash Attention 就在不降低精度的前提下,让大模型训练提速数倍,把显存从 n² 的压力中彻底解放出来。

岗位关联

学懂 Flash Attention,等于掌握了大模型训练中最关键的“内存杠杆”——面对超长序列和超大模型时,你能从 IO 层面找到大幅提速的切入点,这是深度学习工程师进阶的核心实战技能。

目录
  1. 可视化演示
  2. 1. 后厨困境:标准注意力的显存爆炸
  3. 2. 仓库与灶台:IO感知的视野
  4. 3. 分批上菜:分块计算策略
  5. 4. 边做边记:在线Softmax
  6. 5. 不翻旧账:反向传播重计算
  7. 6. 翻台率飙升:性能收益
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

动态演示Flash Attentio的核心机制,通过输入/处理/存储/输出四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Flash Attentio:Flas Flash Attention 分块计算与SRAM利用策略 核心机制可视化 Flash Attentio整体架构与关键组件

1. 后厨困境:标准注意力的显存爆炸

“食堂阿姨把所有盆子端上桌”这个疯狂场面,恰好是标准注意力的真实写照。注意力机制要让句子中每个词去“关注”其他所有词,计算出一张 n 行 n 列的打分表。这张打分表有多大?n=1024 时约 100 万格,n=1 万时直接飙到 1 亿格。打分表既要存储,又要反复读写,显存压力随 n² 膨胀——好比台面面积随菜品种类平方增长,再大的台面也扛不住。

之所以必须产生这么大的矩阵,是因为 softmax 归一化需要看到整行分数。传统流程是这样:先算出 Q×Kᵀ 得分矩阵,把它完整写回高带宽显存 HBM;再读出来做 softmax,于是又得到一张同样大小的概率矩阵 P;最后再读一次与 V 相乘。每一步都在“搬运”整张 n×n 的表,而搬运恰恰是最贵的操作。

所以问题核心不是“计算量大”,而是“搬运量爆炸”。食堂的困境本质是台面太小、来回搬盆太慢。只要还是“整桌端菜”,长序列就永远被显存锁死。

Attention(Q,K,V)=softmax ⁣(QK⊤/d)V\text{Attention}(\mathbf{Q},\mathbf{K},\mathbf{V}) = \text{softmax}\!\left(\mathbf{Q}\mathbf{K}^{\top}/\sqrt{d}\right)\mathbf{V}
标准注意力公式:所有词两两打分、归一化、加权汇总。其中 n×n 的中间矩阵是显存爆炸的元凶。
  1. 计算点积分数Q 与 K 的转置相乘,得到每个查询对所有键的匹配打分。
    S=QK⊤\mathbf{S} = \mathbf{Q}\mathbf{K}^{\top}
  2. 缩放防止爆炸除以 √d,控制分数方差在稳定范围内。
    S~=S / d\tilde{\mathbf{S}} = \mathbf{S}\,/\,\sqrt{d}
  3. Softmax 归一化按行将分数转为加和为 1 的概率。
    P=softmax(S~)\mathbf{P} = \text{softmax}(\tilde{\mathbf{S}})
  4. 加权汇总输出用概率权重对 V 做加权求和,得到最终输出。
    O=PV\mathbf{O} = \mathbf{P}\mathbf{V}

2. 仓库与灶台:IO感知的视野

要解决“搬运”问题,得先看清食堂的后厨结构。食堂有两个地方:一个是地下大仓库,什么食材都有——对应 GPU 的 HBM 高带宽显存,容量大但取货慢;另一个是厨师手边的小灶台——对应 SRAM 片上缓存,容量小得可怜但取用极快,几乎一瞬间。Flash Attention 的第一个关键认知是:大部分时间浪费在“仓库—灶台”之间的路上。

这叫做“IO 感知”:设计算法时,目光从“要做多少次运算”转向“要来回搬多少次数据”。传统 GPU 编程默认显存管够,把中间矩阵全部丢进 HBM;Flash Attention 却像精打细算的厨师,每趟该从仓库拿什么、在灶台上做什么、做完才把成品放回仓库,都规划得清清楚楚。

标准注意力为了算 softmax,需要把巨大的 S 矩阵写回 HBM 再读出来,搬运量是 O(n²)。Flash Attention 的目标是让 HBM 访问量只与输入输出本身成正比,即 O(n),所有中间结果都“焖”在 SRAM 上。

认清“仓库大而慢、灶台小而快”之后,阿姨的改造思路就清晰了:不把整仓库搬空,只在灶台上处理当下的一批货。

Tstandard=O(n2),Tflash=O(n)T_{\text{standard}}=O(n^2),\qquad T_{\text{flash}}=O(n)
标准注意力的显存访问量随序列长度平方增长,Flash Attention 只线性增长。长序列下两者相差一个数量级,这就是名字里 “Flash(闪电)” 的含义。
  1. 标准访问量每个查询都要读写整张注意力表,故为平方级。
    Tstandard=O(n2)T_{\text{standard}}=O(n^2)
  2. Flash 访问量只搬运输入输出块本身,随序列线性增长。
    Tflash=O(n)T_{\text{flash}}=O(n)

3. 分批上菜:分块计算策略

改造后食堂的流程变成这样:阿姨把一餐需要的菜谱拆成几个小组,先拿第一组食材到灶台,炒完出锅送到窗口;再拿第二组……灶台上永远只有正在处理的一小组食材,台面永远清爽。

分块计算(Tiling)就是把这一策略落到矩阵运算上。Flash Attention 不一次算出完整的 n×n 分数矩阵,而是把 Q、K、V 切成若干小块。外层循环遍历 Q 的块,内层遍历 K、V 的块,每一块的计算都在 SRAM 内完成,算完的中间注意力分数表 S 根本不需要写回 HBM。

块的大小取决于灶台容量。设 SRAM 可用空间为 M,要同时放下当前块的 Q、K、V 以及输出,需要满足:

“分批上菜”看似朴素,却一下把灶台利用率拉满:中间产物不落地,HBM 访问量随之降下来。

B≈M3dB \approx \frac{M}{3d}
块越大,搬运次数越少,但 SRAM 放不下;块太小,往返仓库又太频繁。B 是每次上灶的 token 数,d 是每个 token 的向量维度,3 代表 Q、K、V 三份食材。
  1. 分子 M灶台(SRAM)能放下的总元素数量,代表片上空间上限。
    SRAM 容量=M\text{SRAM 容量} = M
  2. 分母 3dQ、K、V 三个矩阵每块各占 B×d 个元素,三份同时上灶。
    三块共需≈3Bd\text{三块共需} \approx 3Bd
  3. 求解 B容量除以三份单块维度,得到能放下的最大 token 数。
    B≈M/(3d)B \approx M / (3d)

4. 边做边记:在线Softmax

分批上菜遇到一个大麻烦:softmax 必须“看到整行”才能计算。以前满台面摆着所有分数,一眼能找到最大值做归一化;现在分数是分批到灶台的,难道要等所有批次齐了才往下算?阿姨想出一个妙招:一边做菜一边记账。每次新菜上灶,她只更新两笔账——目前见过的“最高人气分”和“人气分总和”。

这就是在线 Softmax(Online Softmax)。它打破了“必须等所有分数到齐才归一化”的旧规矩。每当一个新分数块到达,算法用当前块的最大值更新全局最大值 m,同时通过“缩放抵消”把旧账归一化到新标准下,再累加上新块的指数和。因为每一步都做了精确的缩放修正,最终结果和一次性算完整 softmax 完全一致。

设旧块维护的最大值为 m_old、累计指数和为 ℓ_old,新块局部最大值为 m_local,则:

输出也要按比例修正:

靠着“边做边记”,阿姨再也不用等所有菜上齐才开算;台面少、吞吐大,softmax 这个老规矩被在线记账彻底解放。

mnew=max⁡(mold, mlocal)m_{\text{new}} = \max(m_{\text{old}},\, m_{\text{local}})
ℓnew=ℓold e mold−mnew+e mlocal−mnew\ell_{\text{new}} = \ell_{\text{old}}\, e^{\,m_{\text{old}} - m_{\text{new}}} + e^{\,m_{\text{local}} - m_{\text{new}}}
Onew=Oold⋅ℓoldℓnew e mold−mnew+e mlocal−mnewℓnew PlocalVlocal\mathbf{O}_{\text{new}} = \mathbf{O}_{\text{old}}\cdot\frac{\ell_{\text{old}}}{\ell_{\text{new}}}\,e^{\,m_{\text{old}} - m_{\text{new}}} + \frac{e^{\,m_{\text{local}} - m_{\text{new}}}}{\ell_{\text{new}}}\,\mathbf{P}_{\text{local}}\mathbf{V}_{\text{local}}
核心思想:新块到来时,旧数据不重算,而是乘上一个“缩放因子”修正到新的最大值标准下。账本随时更新,结果分毫不差。
  1. 更新最大值新旧两块的全局最大分取较大者,作为新的基准。
    mnew=max⁡(mold, mlocal)m_{\text{new}} = \max(m_{\text{old}},\, m_{\text{local}})
  2. 更新累计指数和旧账按新旧最大值之差缩放,再叠加上新块的指数贡献。
    ℓnew=ℓold e mold−mnew+e mlocal−mnew\ell_{\text{new}} = \ell_{\text{old}}\, e^{\,m_{\text{old}} - m_{\text{new}}} + e^{\,m_{\text{local}} - m_{\text{new}}}
  3. 修正输出旧输出按比例缩放,再与当前块的加权输出合并。
    Onew=Oold⋅ℓoldℓnew e mold−mnew+e mlocal−mnewℓnew PlocalVlocal\mathbf{O}_{\text{new}} = \mathbf{O}_{\text{old}}\cdot\frac{\ell_{\text{old}}}{\ell_{\text{new}}}\,e^{\,m_{\text{old}} - m_{\text{new}}} + \frac{e^{\,m_{\text{local}} - m_{\text{new}}}}{\ell_{\text{new}}}\,\mathbf{P}_{\text{local}}\mathbf{V}_{\text{local}}

5. 不翻旧账:反向传播重计算

训练模型时,光算前向不够,还要反向传播求出梯度、更新权重。以前的食堂结账方式很笨:阿姨每做一道菜都要在笔记本上记下从配料到火候的全部过程——相当于保存所有中间结果——以便月底算总账。笔记本厚度随 n² 增长,后厨很快被账本塞满。

Flash Attention 却选择“不记账”。反向传播需要梯度时,它不去翻旧账,而是把前向过程重做一遍,重新算出那些注意力分数。这当然会多算一些乘法,但避免了巨额 HBM 读写——在 GPU 上,重算一次乘法的代价,远小于从 HBM 读一次大矩阵。

于是前向阶段不再保存 n×n 的注意力矩阵,只保存每块的输出 O 和 softmax 统计量(m、ℓ)。反向时按同样的分块顺序重算 S、P,用这些临时分数求梯度。显存占用顿时从平方级降到线性级:

账本没了,阿姨的后厨又清爽一截。反向传播不再被显存绑架,长序列训练终于跑得动。

Mstandard=O(n2),Mflash=O(n)M_{\text{standard}} = O(n^2),\qquad M_{\text{flash}} = O(n)
用“重新做一遍菜”替代“翻厚厚的账本”:计算能力是廉价的,搬运才是昂贵的,这笔账 Flash Attention 算得很明白。
  1. 标准显存保存完整注意力矩阵,随序列长度平方增长。
    Mstandard=O(n2)M_{\text{standard}} = O(n^2)
  2. Flash 显存只保存 O 与统计量 m、ℓ,线性增长。
    Mflash=O(n)M_{\text{flash}} = O(n)

6. 翻台率飙升:性能收益

改造全部完成时,食堂迎来质的飞跃:台面不堆菜盆、不用等所有菜上齐、也不用背厚厚的账本。阿姨的翻台率飙升,同一时间能接待的顾客成倍增加。

在真实模型中,Flash Attention 的收益立竿见影:论文中 GPT-2 训练时间减少约 15%,BERT 预训练提速超过 3 倍,长序列 Transformer 的训练吞吐提升 3 倍以上。收益随序列长度增加而放大——序列越长,n² 带来的 HBM 搬运压力越大,Flash 的“不搬运”策略就越显威力。

该算法已深度集成进 PyTorch 的 scaled_dot_product_attention、Hugging Face Transformers、vLLM 等主流框架。工程师只需指定 attn_implementation="flash_attention_2" 或让框架自动选择,就能在超长上下文窗口(128k 甚至百万 token)模型训练与推理中获得显著加速。

食堂还是那个食堂,菜还是那些菜,只是不再傻傻地“整桌搬运”。这个小改造,让大模型训练从“被显存卡死”变成“以 IO 为尺度的闪电速度”——这就是 Flash Attention 的故事,也是 IO 感知算法思想的魅力。

TstandardTflash=O(n2)O(n)=n\frac{T_{\text{standard}}}{T_{\text{flash}}} = \frac{O(n^2)}{O(n)} = n
序列越长,加速倍数越接近 n。这就是“翻台率”的量化表达:食堂接待能力随菜品种类线性增长,而不是被台面面积卡死。
  1. 访问量比值标准注意力访问量除以 Flash 访问量。
    O(n2)O(n)\frac{O(n^2)}{O(n)}
  2. 化简结果约去 n 得到 n,加速倍数随序列长度线性放大。
    =n= n

AI 应用场景

场景 1:超长上下文大语言模型预训练

阶段:模型训练

解决的问题:标准注意力在 8k、16k 甚至 128k token 的上下文下,注意力矩阵动辄数十亿格,显存瞬间耗尽,训练根本无法启动。Flash Attention 把 HBM 访问量从 O(n²) 降到 O(n),同一张 GPU 能训练更长的序列。

具体案例:某团队在 8×A100 集群上预训练 7B 参数的对话模型,上下文长度从 4k 提升到 32k。切换 Flash Attention 后,显存占用仅为原来的 1/3,训练吞吐提升约 2.8 倍,团队无需增加硬件即可完成更长上下文的模型训练。

场景 2:长文本推理服务部署

阶段:模型推理与部署

解决的问题:大模型推理时,反复读写 KV Cache 和注意力分数会造成严重的 IO 延迟,用户体验卡顿。Flash Attention 的分块与在线 Softmax 让推理服务在长上下文下也能保持高吞吐。

具体案例:某 SaaS 公司提供文档问答服务,单次请求需处理 50 页 PDF。使用 vLLM 并开启 Flash Attention 后,首 token 延迟降低 40%,并发请求数从 8 提升到 20,服务成本显著下降。

场景 3:多模态大模型的高分辨率图像理解

阶段:多模态模型训练

解决的问题:高分辨率图像会被切分为数百甚至上千个 patch,序列长度远超纯文本任务,标准注意力几乎无法训练。Flash Attention 让多模态模型能“看得更细”。

具体案例:某多模态团队训练图文理解模型时,将图像 patch 数从 576 扩到 1024。借助 Flash Attention,单卡显存从 60GB 降至 32GB,模型在细粒度视觉问答任务上准确率提升 6%。

Python 演示

python51 行
import numpy as np def flash_attention(Q, K, V, block_size=64):    # 简化版 Flash Attention: 分块 + 在线 Softmax    n, d = Q.shape    O = np.zeros_like(Q)    m = np.full((n, 1), -np.inf)    l = np.zeros((n, 1))     for j in range(0, n, block_size):        Kj = K[j:j + block_size]        Vj = V[j:j + block_size]         # 当前块的注意力分数        S_j = Q @ Kj.T / np.sqrt(d)         # 在线更新最大值与累计指数和        m_new = np.maximum(m, S_j.max(axis=1, keepdims=True))        P_j = np.exp(S_j - m_new)        l_new = l * np.exp(m - m_new) + P_j.sum(axis=1, keepdims=True)         # 修正旧输出并叠加当前块贡献        O = O * (l * np.exp(m - m_new)) / l_new        O = O + (P_j @ Vj) / l_new         m, l = m_new, l_new     return O  def standard_attention(Q, K, V):    # 标准实现: 完整计算 n*n 矩阵    d = Q.shape[1]    S = Q @ K.T / np.sqrt(d)    P = np.exp(S - S.max(axis=1, keepdims=True))    P = P / P.sum(axis=1, keepdims=True)    return P @ V  if __name__ == "__main__":    np.random.seed(0)    n, d = 128, 16    X = np.random.randn(n, d)     O_flash = flash_attention(X, X, X, block_size=32)    O_std = standard_attention(X, X, X)     diff = np.abs(O_flash - O_std).max()    print("max abs diff:", diff)    assert diff < 1e-10, "Flash Attention 与标准结果不一致!"    print("result: match")
目的:用 NumPy 实现简化版 Flash Attention,验证分块加在线 Softmax 的计算结果与标准注意力完全一致。
  1. S_j = Q @ Kj.T / np.sqrt(d)只计算当前 K 块与全部 Q 的分数,避免生成完整 n×n 矩阵。
  2. m_new = np.maximum(m, S_j.max(...))边做边记,更新“目前见过的最大分数”。
  3. l_new = l * np.exp(m - m_new) + P_j.sum(...)旧账缩放后加上新块贡献,维护累计指数和。
  4. O = O * (l * np.exp(m - m_new)) / l_new按比例修正旧输出,抵消最大值变化的影响。
  5. O = O + (P_j @ Vj) / l_new把当前块的加权结果累加到输出上。
  6. diff = np.abs(O_flash - O_std).max()对比两种实现的最大误差,证明在线算法数值等价。

常见误区

误区很多人一听“加速”,理所当然认为 Flash Attention 减少了 FLOPs,算法变聪明了,所以算得快。

正解Flash Attention 的 FLOPs 和标准注意力几乎一样,它真正省掉的是 HBM 读写次数。类比食堂:阿姨做的菜一道没少,只是不再把整座后厨搬到台面。GPU 上矩阵乘法极快,而显存读取极慢,省 IO 比省运算更有效。

为何常见:人们习惯用“计算复杂度”衡量算法效率,忽视了硬件上“数据搬运”才是大模型训练的真正瓶颈。

误区有人担心在线 Softmax 是“近似”算法,分块更新会引入精度损失,训练出来模型会变差。

正解在线 Softmax 的每一步都做了精确的缩放修正,数学上与普通 Softmax 数值等价,误差通常在机器精度(1e-10 量级)以下。正如阿姨边做菜边记账,最后账目和一次性盘点完全吻合,只是不用等全部菜上齐。

为何常见:看到公式里有多个指数和缩放因子,直觉会以为是近似,其实每一步等式都是严密的恒等变换。

误区不少开发者认为 Flash Attention 是训练专用优化,推理时 KV Cache 已经是线性内存,没必要用。

正解推理同样有巨大收益。自回归生成时,每个 token 都要与历史 KV 块做注意力计算,分块策略和减少 HBM 读写同样适用。vLLM、TensorRT-LLM 等主流推理框架都已内置 Flash Attention,长上下文服务延迟显著降低。

为何常见:对 Flash Attention 的理解停留在“解决训练显存爆炸”,忽略了它本质是解决“注意力 IO 瓶颈”这一通用问题。

面试题

Q1. 标准注意力机制中,注意力分数矩阵的空间复杂度是多少?

单选题 · easy

  • A.常数内存 O(1)
  • B.线性内存 O(n)
  • C.平方内存 O(n²)← 正确答案
  • D.立方内存 O(n³)

答案:C。标准注意力需要显式保存 QKᵀ 和 softmax 概率矩阵,二者都是 n×n 大小,因此空间复杂度为 O(n²)。就像食堂台面上摊开的菜盆数量随菜品平方增长,序列一长显存立刻爆满。

Q2. Flash Attention 获得加速的根本原因是什么?

单选题 · mid

  • A.降低 FLOPs 算力开销
  • B.减少 HBM 读写次数← 正确答案
  • C.大幅提升 GPU 主频
  • D.完全取消注意力计算

答案:B。Flash Attention 没有显著减少浮点运算量,而是通过分块计算把中间结果“焖”在 SRAM 上,避免在 HBM 中反复读写。如同食堂阿姨不再来回搬整座后厨,省下的是“搬运”时间而非“做菜”时间。

Q3. 关于 HBM 与 SRAM,下列说法正确的有哪些?

多选题 · mid

  • A.HBM 容量大但带宽受限← 正确答案
  • B.SRAM 更快且容量更小← 正确答案
  • C.HBM 读写速度远超 SRAM
  • D.SRAM 位于 GPU 芯片内部← 正确答案

答案:ABD。HBM 是“大仓库”,容量大但读写慢;SRAM 是“小灶台”,容量小但极快,物理上位于芯片内部。C 选项恰好说反,SRAM 读写速度远高于 HBM。

Q4. 在线 Softmax 需要持续维护哪两个统计量?

单选题 · mid

  • A.行最大值与累计指数和← 正确答案
  • B.行最小值与累计乘积
  • C.列平均值与累计方差
  • D.矩阵范数与特征向量

答案:A。在线 Softmax 的核心是维护“目前见过的最大值 m”和“累计指数和 ℓ”。新块到达时,用新旧最大值的差值对旧账做缩放修正,再叠加新块贡献,最终结果与全局 Softmax 等价。

Q5. Flash Attention 的反向传播不保存注意力矩阵,它采用什么策略?

单选题 · hard

  • A.随机丢弃中间结果
  • B.低精度近似存储
  • C.前向重计算结果← 正确答案
  • D.外部内存交换数据

答案:C。反向传播需要梯度时,按分块顺序把前向过程重新算一遍,得到临时注意力分数再求导。重算乘法的开销远小于从 HBM 读大矩阵,如同阿姨不背厚账本,需要时重新做一遍菜。

Q6. Flash Attention 适合哪些应用场景?

多选题 · mid

  • A.超长序列模型训练← 正确答案
  • B.大模型推理部署← 正确答案
  • C.超短序列文本分类
  • D.高吞吐自回归生成← 正确答案

答案:ABD。Flash Attention 在长序列和高吞吐场景收益最大,因为这时 n² 的 HBM 搬运量被显著削减。而超短序列本身搬运压力小,优化空间有限,收益不明显。

Q7. 为什么“重计算”比“保存中间结果”在 GPU 上更划算?

单选题 · mid

  • A.重计算省显存且计算比读写便宜← 正确答案
  • B.重计算不需要消耗任何算力
  • C.保存中间结果完全不占显存
  • D.重计算会自动提高精度

答案:A。GPU 上矩阵乘法吞吐远高于 HBM 带宽,重算一遍注意力的时间代价,小于从 HBM 读取超大矩阵的时间代价。就如同厨师重新炒一道菜,比去仓库翻箱倒柜找旧账更快。

Q8. 分块计算让哪些中间结果无需写回 HBM?

多选题 · hard

  • A.注意力分数矩阵 QKᵀ← 正确答案
  • B.Softmax 概率矩阵 P← 正确答案
  • C.输入词嵌入向量表
  • D.最终输出特征向量 O

答案:AB。Flash Attention 将 QKᵀ 和 softmax 的中间矩阵都留在 SRAM 内完成计算,因此不再写回 HBM。输入嵌入与最终输出 O 属于输入输出本身,仍要经过 HBM 搬运。

Q9. HBM(高带宽显存)在 GPU 中主要承担什么角色?

单选题 · easy

  • A.临时保存大容量数据← 正确答案
  • B.执行高速并行加法
  • C.替 CPU 编译指令
  • D.管理网络通信协议

答案:A。HBM 是 GPU 的主内存,容量大但速度不如片上缓存,用于保存权重、激活值和中间张量。Flash Attention 优化的核心,就是减少对这块“大仓库”的访问。

Q10. 在线 Softmax 相比普通 Softmax 最关键的不同之处是什么?

单选题 · hard

  • A.分块到达即可更新结果← 正确答案
  • B.修改了归一化数学定义
  • C.彻底移除指数运算
  • D.只支持单个查询向量

答案:A。普通 Softmax 必须等整行分数齐备才能计算,在线 Softmax 让数据分块到达时就能滚动更新,且数学完全等价。它没有改变归一化定义,也没移除指数运算,而是把“等齐再算”变成“边到边算”。