惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tailwind CSS Blog
C
CERT Recently Published Vulnerability Notes
P
Proofpoint News Feed
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
Help Net Security
Help Net Security
月光博客
月光博客
N
News and Events Feed by Topic
Cloudbric
Cloudbric
博客园 - 司徒正美
L
LangChain Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tenable Blog
The Register - Security
The Register - Security
The Hacker News
The Hacker News
I
InfoQ
The Last Watchdog
The Last Watchdog
MyScale Blog
MyScale Blog
Schneier on Security
Schneier on Security
WordPress大学
WordPress大学
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
K
Kaspersky official blog
L
LINUX DO - 热门话题
N
News | PayPal Newsroom
F
Fortinet All Blogs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Security @ Cisco Blogs
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
C
Cisco Blogs
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
Latest news
Latest news
PCI Perspectives
PCI Perspectives
T
The Blog of Author Tim Ferriss
P
Palo Alto Networks Blog
T
Tor Project blog
Project Zero
Project Zero
云风的 BLOG
云风的 BLOG
Webroot Blog
Webroot Blog
Attack and Defense Labs
Attack and Defense Labs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

Пусть этот камень будет более крепким, чем человек

【琐记】烟火与尘埃 【Triton】Triton实现矩阵乘 【LLM推理加速】FlashAttention 【LLM推理加速】PagedAttention LLM基础知识【1】 Transformer模型 【AI编译】LayerGroup Tiling Tile的疑惑和思考 【AI编译】深度优先的Tile调度,万事大吉? 【AI编译】多级流水线Tile调度策略 【CUDA C++】GPU内存使用【3】 【AI编译】Cache缓存地址映射 【CUDA C++】GPU存储【2】 【CUDA C++】GPU基本介绍【1】 【00】0序章-不受欢迎的来客 【转载】我来了——持续低熵 【Halide】调度优化【2】 【感想】写作进度报告5 【Halide】调度优化【1】 【转载】北大中文男足战报2 【BYOC】TVM切分子图 【转载】北大中文男足战报1 【AI编译】张量生命周期管理 SystemC 用寄存器同步建模方法 【脉动阵列】脉动阵列类型 【im2col】AScend conv accelerate 【感想】写作进度报告4 【BYOC】TVM添加自定义编译器 ccompiler 【感想】写作进度报告3 【Tengine】推理流程脑图【2】 【Tengine】推理流程脑图【1】 【NCNN】学习ncnn模型转换 【编译器】使用llvm编译自定义语言【3】编译 object 【编译器】使用llvm编译自定义语言【2】转llvm IR 【编译器】使用llvm编译自定义语言【1】构建AST 【AI编译】如何进行内存分配 【感想】写作进度报告2 【AI编译】layer-group之后如何tiling 【AI编译】如何进行layer-group 【量化】连续卷积层首尾量化的可行性 【Gemm】内存对齐 【gemm】Gemm计算加速 【TVM】通过代码学习编译流程【5】FuseOps 【TVM】通过代码学习编译流程【6】CodeGen 【TVM】通过代码学习类【3.5】Pass 【TVM】通过代码学习编译流程【4】BuildRelay 【AI编译】Tiling操作能优化什么时间 【TVM】通过代码学习编译流程【3】模型编译 【TVM】通过代码学习编译流程【2】模型转换 【TVM】通过代码学习编译流程【1】必要知识 【感想】写作进度报告1 【Winograd】卷积加速算法原理及实现 SystemC 等待异步事件解决方案 【TVM】Python脚本实现模型编译和保存 【推理引擎】常见AI推理框架 【3D建模】T110E3卡迪夫蓝调皮肤模型 【TVM】C++部署运行TVM 【推理引擎】NCNN和Tengine量化推理逻辑对比 【3D建模】IS-7攻城锤流纹岩皮肤展示 【TVM】根据例子走通代码库 博客汇总目录 【Im2Col】卷积加速算法【2】NHWC 【Im2Col】卷积加速算法【1】 NCHW openBlas库的安装与简单使用 C语言工程调用Cpp库解决方案 foo Hello World
【LLM推理加速】Online Softmax
Post author: XianMu@Пусть этот камень будет более крепким, чем ч · 2026-05-01 · via Пусть этот камень будет более крепким, чем человек

# 前言

本文介绍 VLLM 的 Online Softmax。
本文大部分内容来自于 【手撕 LLM-Flash Attention】从 softmax 说起,保姆级超长文!!

参考链接:Transformer 模型详解(图解最完整版)Attention is All You NeedPytorch 版本的 Transformer 实现一文了解 Transformer 全貌(图解 Transformer)大模型推理加速:看图学 KV Cache手撕大模型|KVCache 原理及代码解析FlashAttention 深度解析:从数学原理到工程实现Flash Attention 原理详解 (含代码讲解)【手撕 LLM-Flash Attention】从 softmax 说起,保姆级超长文!!

softmax 是 LLM 中的重要组成部分。

Softmax公式

python 实现代码:

X = torch.tensor([-0.3, 0.2, 0.5, 0.7, 0.1, 0.8])
X_exp_sum = X.exp().sum()
X_softmax_hand = torch.exp(X) / X_exp_sum
print(X_softmax_hand)

输出结果:

tensor([0.0827, 0.1364, 0.1841, 0.2249, 0.1234, 0.2485])

# Safe Softmax

safe Softmax公式

从 Safe Softmax 公式上看,输入元素统一减去全局最大值。减去最大值是为了防止指数运算 e^x 出现 上溢(inf)问题,保证数值稳定。
FlashAttention online Softmax、所有工业级 Attention 全部强制做这一步,是数学 + 浮点硬件的双重刚需。
以 LLM 为例,就算模型已经收敛,注意力分数 QK^T 依然天然会很大,大约在正负 10 左右浮动。attention 部分的推理一般采用 FP16,FP16 最大安全值 ≈ 65504。而 exp (11) 就已经濒临溢出,exp (12) 直接 NaN。
attention公式

所以大模型注意力得分需要做归一化处理(除以 d 的开方),这个缩放操作,是为了把分数强行压到小范围。
既然已经压缩了,是不是 Softmax 就不需要减全局最大值了?
不是的,缩放负责日常降压,减全局最大值负责兜底。Safe Softmax 在工业上是必不可少的。
转换公式

从上式可以看到,Safe Softmax 与 Softmax 完全等价,完全不改变输出概率分布。

X_max = X.max()
X_exp_sum_sub_max = torch.exp(X-X_max).sum()
X_safe_softmax_hand = torch.exp(X - X_max) / X_exp_sum_sub_max
print(X_safe_softmax_hand)

输出结果:

tensor([0.0827, 0.1364, 0.1841, 0.2249, 0.1234, 0.2485])

# Online Softmax

LLM 推理对内存占用敏感,注意力计算 QKT 占用大量空间,能不能只加载一部分 QKT 进行计算呢?
Online Softmax 目的就是为了只加载一部分 QK^T 进行计算。
假设我们将所有元素分成两块,分别是 [0,N] 和 [N+4, 2N]。我们需要单独计算各块 softmax 所需要的分母 l 和最大值 m
计算公式

然后更新全局最大值 m :
计算公式

再用以下方式更新全局分母 l
计算公式

Online Softmax:
计算公式

X_block = torch.split(X, split_size_or_sections = 3 , dim = 0) 
print(X)
print(X_block)
X_block_0_max = X_block[0].max()
X_block_0_sum = torch.exp(X_block[0] - X_block_0_max).sum()
X_block_1_max = X_block[1].max()
X_block_1_sum = torch.exp(X_block[1] - X_block_1_max).sum()
X_block_1_max_update = torch.max(X_block_0_max, X_block_1_max) 
X_block_1_sum_update = X_block_0_sum * torch.exp(X_block_0_max - X_block_1_max_update) \
                     + torch.exp(X_block[1] - X_block_1_max_update).sum() 
X_block_online_softmax = torch.exp(X - X_block_1_max_update) / X_block_1_sum_update
print(X_block_online_softmax)

输出:

tensor([-0.3000,  0.2000,  0.5000,  0.7000,  0.1000,  0.8000])
(tensor([-0.3000,  0.2000,  0.5000]), tensor([0.7000, 0.1000, 0.8000]))
tensor([0.0827, 0.1364, 0.1841, 0.2249, 0.1234, 0.2485])

# multi-block Online Softmax

将输入元素拆成更多份的话,计算方式也差不多:

X_block = torch.split(X, split_size_or_sections = 2, dim = 0) 
X_block_0_max = X_block[0].max()
X_block_0_sum = torch.exp(X_block[0] - X_block_0_max).sum()
X_block_1_max = X_block[1].max()
X_block_1_sum = torch.exp(X_block[1] - X_block_1_max).sum()
X_block_2_max = X_block[2].max()
X_block_2_sum = torch.exp(X_block[2] - X_block_2_max).sum()
M = [X_block_0_max, X_block_1_max, X_block_2_max]
L = [X_block_0_sum, X_block_1_sum, X_block_2_sum]
M_old = torch.tensor([0.0])
L_old = torch.tensor([0.0])
for i in range(len(M)):
    M_new = torch.max(M[i], M_old) 
    L_new = L_old * torch.exp(M_old - M_new) \
            + torch.exp(X_block[i] - M_new).sum() 
    M_old = M_new
    L_old = L_new
X_multi_block_online_softmax = torch.exp(X - M_old) / L_old

借助 Online Softmax,可以只加载一部分 QK^T 进行计算。

# 后记

本博客目前以及可预期的将来都不会支持评论功能。各位大侠如若有指教和问题,可以在我的 github 项目 或随便一个项目下提出 issue,并指明哪一篇博客,看到一定及时回复!