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

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

博客园 - marsggbo

Eurosys26 | FineMoE如何用「细粒度」打破MoE推理的显存-延迟死局 Fast26 | LLM 推理启动慢?华为用一个「可编程 Page Cache」把模型加载砍了 79% KV Cache 的两层存储到底卡在哪?FAST'26 这篇论文给出了答案 NeurIPS24 | 把Dense LLM变身MoE还提速 ICML25 | EPIC:KV Cache 复用的「编译-链接」范式(附可运行代码复现) KV Cache 复用的第三条路:FAST 2026 CacheSlide 是怎么解决 Agent 推理的位置漂移问题的 MoE 推理的内存墙,被一块多芯粒芯片打穿了? KVCOMM:让多 Agent 系统的 KV Cache 真正“通起来”,TTFT 直接砍掉 7.8 倍 NSDI26 | DroidSpeak让不同 LLM 之间共享 KV Cache TokenDance 解决多 Agent LLM 推理的 KV Cache 冗余问题 当 AI 开始学会"记住":LLM Agent 记忆系统的统一视角 【转载】ACM MM 投稿论文模板修改成投稿模式 尝试从源头理解 SVD 原理和计算 LLM 场景下的强化学习技术扫盲 解决 Overleaf 中插入 PDF 图片失败的问题:排查与修复 Tmux ctrl+B快捷键失效处理办法 对抗训练综述学习笔记 【转知乎回答】一文看懂 LLaMA 中的旋转式位置编码(Rotary Position Embedding) 二进制中为什么负数是正数取反再加一 leetcode 常见题型代码总结 Prompt-Tuning、P-Tuning和Prefix-Tuning区别和代码实现【转】 Deepspeed ZeRO系列算法原理+通信开销详解 NSCC集群使用笔记 Huggingface Transformers实现张量并行的小坑 set/get_output_embeddings Pytorch 如何使用 storage 实现参数 offload? TACC 集群使用笔记 图解 vLLM 的推理调度策略 大模型推理框架 vLLM 源码解析(二):Block 模块分配和管理 OpenAI 的视频生成大模型Sora的核心技术详解(一):Diffusion模型原理和代码详解 大模型推理框架 vLLM 源码解析(一)
LoRA fine-tune吞吐量提升1.96倍!LoRAFusion如何把内存带宽浪费和pipeline bubble一起干掉
marsggbo · 2026-05-16 · via 博客园 - marsggbo

Eurosys26 | LoRAFusion 把内存带宽浪费和pipeline bubble一起干掉,吞吐量提升1.96倍

原文:LoRAFusion: Efficient LoRA Fine-Tuning for LLMs


1. 前言

做过 LLM fine-tune 的同学应该都知道,LoRA 是当前 PEFT 方法里最主流的选择。只引入少量低秩参数,显存省下来了,效果也不差。

但你有没有想过:LoRA 参数只有全参数的 0.3% 不到,为什么加上 LoRA 之后训练速度反而掉了 40%?

这个数字是真实测出来的,不是理论估算。Fine-tune LLaMa-3.1-70B,加上 LoRA(rank=16)之后,训练 throughput 直接下降 40%。本质上是一个让人有些细思极恐的问题:参数只加了 0.3%,计算量也没增加多少,但速度掉了这么多,钱花在哪了?

今天这篇 EuroSys '26 的工作 LoRAFusion 把这个问题剖析得很清楚,顺带还解决了另一个在多任务 fine-tune 场景里被严重忽视的问题:多个 LoRA job 并行时的 pipeline bubble 和 GPU 负载不均衡

代码已开源:github.com/CentML/lorafusion


2. 背景:LoRA 的参数结构和 fine-tune 痛点

先简单回顾一下 LoRA 的公式。对于一个预训练权重矩阵 \(W \in \mathbb{R}^{k \times n}\),LoRA 注入两个低秩矩阵 \(A \in \mathbb{R}^{k \times r}\)\(B \in \mathbb{R}^{r \times n}\)\(r \ll k, n\)):

\[Y = XW + \alpha \cdot (XA)B = XW + \alpha \cdot SB \]

其中 \(S = XA\) 是中间结果(维度小),\(\alpha\) 是缩放系数。fine-tune 过程中 \(W\) 冻结不更新,只更新 \(A\)\(B\)

以 LLaMa-3.1-70B 为例:

  • 全参数 fine-tune:仅模型状态就需要约 1120 GB 显存(参数、梯度、优化器状态)
  • LoRA(rank=16)fine-tune:只需约 142 GB 显存,额外参数量仅占 0.29%

显存省了将近 8 倍,但训练速度呢?

如下图,LoRA linear 层和普通 frozen linear 层的吞吐量对比:

LoRA vs Frozen Linear 前向/反向吞吐量对比

不管 token 数和 rank 是多少,LoRA linear 比 frozen linear 慢了约 40%(forward)和 36%(backward)。torch.compile 几乎没有帮助。这是为什么?


3. 问题分析:罪魁祸首是内存带宽,不是计算量

3.1 内存访问是瓶颈

如下图,一个 LoRA linear 层的运行时细分:

LoRA 模块运行时分布分析

运行时主要分三类:

  1. Frozen GEMM\(XW\)):compute-bound,占 59%/60%(前向/反向)
  2. LoRA GEMM\(XA\)\(SB\)):memory-bound,前向占 10.76%,反向占 20.37%
  3. Element-wise 操作(dropout、乘法、加法):memory-bound,前向占 30.46%,反向占 17.49%

LoRA 的下投影 \(S = XA\) 的算术强度 \(\mathbb{I}\) 是:

\[\mathbb{I} = \frac{1}{\frac{1}{r} + \frac{1}{n} + \frac{1}{m}} \ll \mathbb{B} \]

由于 \(r\) 很小(比如 16),这个算术强度远低于 H100 的硬件 balance 点(FP16 约 295),确认是 memory-bandwidth-bound

更直接的数据:用 NVIDIA Nsight Compute 测量,LoRA 模块的 GPU global memory 读写流量比 frozen linear 增加了 2.64 倍

结论很明确:LoRA 的 runtime overhead 根本原因是大 activation tensor 的重复内存访问,不是 FLOPs 增加。

3.2 Multi-LoRA 的机会被忽视了

现实中的 fine-tune 场景经常同时跑多个 LoRA job——超参搜索、多任务适配、多租户服务。这些 job 共用同一个 base model,显存开销很小,完全可以放在同一批 GPU 上跑。

但现有系统(比如 mLoRA)基本是各跑各的,错过了两个重要的优化机会:

如下图,随 global batch size 增大,理想吞吐量的提升幅度:

增大 global batch size 对 LLaMa-3.1-70B 吞吐量的影响

机会 1:增大 global batch size,降低分布式并行 overhead

把多个 job 的 sample 合并,global batch size 从 4 增到 32,FSDP 的理想吞吐量提升 84%,Pipeline Parallelism 提升 45%。原因是更大的 batch 能更好地 overlap 通信和计算(FSDP),以及填满 pipeline stages 减少 bubble(PP)。

机会 2:跨 job 打包样本,缓解 GPU 负载不均衡

实际数据集的 sequence length 分布差异很大(XSum/CNN/WikiSum 各不相同),导致每个 microbatch 的 token 数波动剧烈。如下图,同一 microbatch_size=4 下,token 数在不同样本间差异悬殊:

这种不均衡在 FSDP 下导致各 rank 等待最慢的那个,在 PP 下形成更多 bubble。如果把多个 job 的样本混合打包,可以有效平衡每个 microbatch 的 token 数,理论上可以带来最高 2.28 倍的吞吐量提升

如下图,实际测量到的 LoRA fine-tune 相比理想固定长度场景的性能下降(最高约 30%):

实际 LoRA fine-tune vs 理想场景的性能差距

这是整个 multi-LoRA fine-tune 领域的核心矛盾:现有系统要么不支持多 job 并行,要么支持了但忽略了 load balance 和 kernel 层面的 redundant memory access。


4. LoRAFusion 的方案

两个层面的优化,对应两个问题:

如下图,LoRAFusion 整体系统架构:

LoRAFusion 系统架构和工作流

4.1 Kernel 层面:FusedLoRA 和 FusedMultiLoRA

核心思路:图分裂(Graph Splitting)+ 横向融合

一个直觉上的做法是把整个 LoRA 计算图 fuse 成一个 kernel。但这有两个问题:

  • Frozen GEMM(\(XW\))是 compute-bound,需要精心 tiling,如果和其他操作混在一起,共享的寄存器/shared memory 会破坏最优 tiling
  • \(XA\)\((XA)B\) 之间有 producer-consumer 依赖,naive fusion 要么 recompute,要么跨 thread block 同步,都会引入额外开销

LoRAFusion 的解法是在中间张量 \(S = XA\)(维度小,rank 维度)处分裂计算图

如下图,三种融合策略的对比(recompute / synchronization / graph-split):

LoRA 融合策略对比:全图融合 vs 分裂图融合

\(S\) 的大小是 \(m \times r\)\(r\) 很小),读写它代价很低。在 \(S\) 处分裂后:

  • \(S\) 之前的操作(dropout + \(XA\))fuse 成一个 kernel,消除大 activation tensor 的重复加载
  • \(S\) 之后的操作(\(XW\)\(\alpha \cdot SB\))fuse 成另一个 kernel,避免 frozen GEMM 被干扰

如下图,FusedLoRA 的 kernel 设计(前向和反向):

FusedLoRA kernel 设计示意图

具体实现:

  • Forward 前向:① dropout + 下投影(\(X \to S\))fuse 成一个 kernel;② frozen GEMM(\(XW\))和 LoRA 上投影(\(\alpha SB\))fuse 成一个 kernel,直接累加输出,消除一次大张量的读写
  • Backward 反向:③ fuse \(dS\)\(dB\) 的计算,消除 \(dY\) 的重复加载;⑤ fuse base model 的梯度计算和 LoRA path 操作,消除 partial output 梯度的重复读写

内存流量实测减少 34%~37%,不需要 recompute,不需要 synchronization。

接下来,扩展到 FusedMultiLoRA,支持同时处理来自不同 job 的 adapter:

如下图,FusedMultiLoRA 的 tile 级 routing 机制:

FusedMultiLoRA:tile 级 adapter 路由

每个 input tile 带一个 adapter ID,kernel 执行时动态查表,加载对应的 \(A\)\(B\) 矩阵并应用正确的 dropout 和 scaling。Base model 的计算在所有 token 间共享,adapter-specific 逻辑按 tile 独立处理。反向传播时,梯度同样按 adapter ID 路由回各自的 adapter,互不干扰。

4.2 Scheduling 层面:Multi-LoRA 自适应调度

这是 LoRAFusion 的另一个核心贡献,解决的是如何把多个 job 的样本打包成均衡的 microbatch。

如下图,Multi-LoRA 调度器的三步工作流:

Multi-LoRA 调度工作流(adapter 分组 + MILP 打包 + 跨 batch 合并)

整个调度分三步:

Step 1:Adapter 分组(Bubble Lemma)

Pipeline 并行下有一个依赖约束:adapter \(i\) 的 global batch \(j\) 的 sample,在它的 backward 完成之前,同一 adapter 的 global batch \(j+1\) 的 sample 不能开始 backward。简单说就是:同一个 adapter 的相邻两个 global batch,在时间线上必须间隔至少 \(S-1\) 个 microbatch(\(S\) 是 pipeline stages 数)。

LoRAFusion 通过把 adapter 按 sequence length 分布分组,并在相邻组之间保持这个间隔,来满足 Bubble Lemma。组内采用"头尾配对"——长 sequence 和短 sequence 的 adapter 配对,提升负载均衡。

Step 2:两阶段 MILP bin-packing

组内的样本需要被打包到 microbatch 里(每个 microbatch 有 token 容量上限)。目标是:①最小化 microbatch 数;②让最空的 microbatch 尽量空(为后续合并留空间)。

这是一个 bin-packing 问题,用两阶段 MILP 求解:

  • Stage 1:最小化 bin(microbatch)数 \(B^*\)
  • Stage 2:固定 \(B = B^*\),最大化最空的 bin 的空闲空间

MILP 设置超时,超时则 fallback 到贪心算法。多个 global batch 的打包并行用 multiprocessing 执行。

Step 3:跨 batch 合并

每个 global batch 的最后一个 microbatch 往往是欠填充的(last microbatch 问题)。LoRAFusion 在满足 Bubble Lemma 的前提下,把下一个 global batch 的开头 token 挪进来填充,减少 pipeline bubble。

系统异步性保障:调度时间线性增长(每个样本约 4ms CPU 时间),但调度本身和 GPU 训练并行执行,overhead 被隐藏在 GPU 计算时间内。


5. 实验设置和结果

5.1 实验设置

  • GPU:NVIDIA H100(80GB,NVLink)和 L40S(48GB,PCIe)
  • 模型:LLaMa-3.1-8B、Qwen-2.5-32B、LLaMa-3.1-70B
  • 数据集:XSum、CNN/DailyMail、WikiSum(摘要任务)
  • 实验配置:同时 fine-tune 4 个 LoRA adapter
  • Baseline:Megatron-LM(FSDP 和 PP)、mLoRA

5.2 端到端结果

如下图,在 H100 上训练 4 个 LoRA adapter 的端到端 throughput 对比:

H100 上端到端训练吞吐量对比

核心数字:

  • 相比 Megatron-LM:最高 1.96×,平均 1.47× 提升
  • 相比 mLoRA(SOTA multi-LoRA):最高 1.46×,平均 1.29× 提升

不同模型的收益规律:

  • LLaMa-3.1-8B(单卡):平均 1.26×,主要来自 FusedLoRA kernel,因为单卡不存在 pipeline bubble
  • Qwen-2.5-32B / LLaMa-3.1-70B(多卡分布式):平均 1.42×/1.64×,调度层面的优化贡献更大
  • WikiSum 数据集(sequence length 方差极大):LoRAFusion 在 baseline 出现 OOM 的情况下仍能稳定运行

如下图,在 L40S 上的对比结果:

L40S 上端到端训练吞吐量对比

L40S 的绝对提升略小(单卡显存有限,限制了 batch size),但 LoRAFusion 依然保持领先。

5.3 扩展性

如下图,在 4、8、16 卡 H100 上的扩展性对比(DP scaling vs Job scaling):

LoRAFusion 在 4/8/16 张 H100 上的扩展性

关键发现:Job-level scaling(用更多 GPU 跑更多并行 job)优于 DP scaling(用更多 GPU 扩展同一 job),在 8 和 16 卡时分别高出 1.18× 和 1.25×。

原因很直接:更多的 job 提供了更大的 global batch,调度灵活性更高,pipeline bubble 更少。LoRAFusion 同时兼容 DP scaling,在 DP scaling 场景下也比 Megatron-LM 快 1.78×,比 mLoRA 快 1.50×。

5.4 Kernel 性能

如下图,FusedLoRA 和 FusedMultiLoRA kernel 的吞吐量对比:

FusedLoRA kernel 前向/反向吞吐量对比

  • FusedLoRA:平均 1.27×(最高 1.39×)
  • FusedMultiLoRA:平均 1.17×(最高 1.24×)

FusedMultiLoRA 在反向传播时需要额外累加多个 adapter 的梯度,有轻微 overhead,但整体依然显著优于 baseline。

如下图,内存流量实测(Nsight Compute):

GPU DRAM 内存流量对比(不同 kernel)

DRAM 总流量减少 34%~37%,和理论分析完全对应。

5.5 Pipeline Bubble 消减

如下图,不同 adapter 数量下 LoRAFusion 的 pipeline bubble 比率:

不同方法下的 pipeline bubble 比率

  • Megatron-LM(单 adapter):48.79%
  • mLoRA(4 adapter):34.11%
  • LoRAFusion(4 adapter):11.09%

bubble 从将近一半降到一成,调度的效果非常明显。

5.6 Speedup 分解

如下图,LoRAFusion 在 LLaMa-3.1-70B(4 H100)上的加速分解:

LLaMa-3.1-70B 上各组件的加速贡献分解

从 Megatron-LM baseline 开始,各组件的贡献:

累加组件 相对 Megatron-LM 加速
+ FusedLoRA 1.13×
+ Multi-LoRA Zero-Bubble PP 1.50×
+ FusedMultiLoRA 1.72×
+ Adaptive Scheduling 2.05×

kernel fusion + pipeline 调度 + 负载均衡,三个维度缺一不可,组合起来才是最终的 2× 提升。


6. 一些延伸思考

为什么 torch.compile 解决不了这个问题?

torch.compile 有 compiler-based fusion,但测试结果是对 forward pass 几乎零收益,backward 只有可以忽略的微小改善。原因是 LoRA 的计算图结构对 torch.compile 的 fusion 规则来说不够"友好"——大 activation tensor 在多个分支之间共享,编译器难以自动找到减少内存 traffic 的最优分裂点。LoRAFusion 的 graph-splitting 策略本质上是一个领域特定的 kernel 设计,需要对 LoRA 结构有深入理解。

Kernel 可以直接插入现有系统?

是的,FusedLoRA kernel 可以作为 plug-and-play 替换,直接接到 PEFT Library、LLaMa-Factory 等现有系统上。论文中验证了数值精度等价,不影响模型质量。这个"即插即用"的设计思路值得借鉴——优化和算法分离,降低落地门槛。

LoRA 变体怎么办(DoRA/VeRA)?

论文讨论了可扩展性:这些变体的核心 LoRA 计算结构不变,只是在外面套了 prologue/epilogue 函数,LoRAFusion 的 kernel 可以通过添加这些函数来扩展。更通用的方案是集成进 torch.compile 的 compiler 框架,未来工作。


7. 总结

LoRAFusion 找到了两个被现有系统忽视的问题,并给出了系统性的解法:

  1. 内存带宽浪费:LoRA 参数只有 0.3%,但大 activation tensor 的重复加载导致 40% 吞吐量下降。LoRAFusion 用 graph-splitting + 横向 kernel fusion 把内存流量减少 34%~37%
  2. Multi-LoRA 机会未被利用:多 job 并行时的 pipeline bubble 和 load imbalance。LoRAFusion 用 Bubble Lemma 约束的 adapter 分组 + 两阶段 MILP bin-packing,把 bubble 从 48% 压到 11%

两者结合,端到端吞吐量最高提升 1.96×(平均 1.47×),而且代码已经开源,kernel 部分可以直接插到现有系统里。

对做 LLM fine-tune 的工程师来说,这篇工作的实用价值很直接。感兴趣的可以去试一下:github.com/CentML/lorafusion