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

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
H
Help Net Security
V
Visual Studio Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
The Cloudflare Blog
Martin Fowler
Martin Fowler
D
Docker
腾讯CDC
F
Fortinet All Blogs
雷峰网
雷峰网
GbyAI
GbyAI
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - 叶小钗

博客园 - marsggbo

GPU 算力没在算模型,在等 CPU 发号施令——CUDA Graph 是怎么解决这件事的 推理模型做 decode,GPU 只有 3% 在干活——SparseSpec 把稀疏 Attention 变成了 2.1× 加速 vllm v1 源码精读(三):KV Cache 管理、Chunked Prefill 与异步架构 vllm v1 源码精读(二):generate() 计算流——model.forward() 在哪里被调用? vllm v1 源码精读(一):为什么要重写,以及 LLM() 这行代码背后发生了什么 160 个 AI 比 80 个效果更差?这篇论文量化了一件大家隐约知道但说不清楚的事 ICLR'25 | SWIFT:不训练不搜索,Self-Speculative Decoding 的即插即用版 2025 | SSD for dLLMs:扩散语言模型也能用推测解码,最高 3.46× arXiv'26 | SSD for ASR:用 CTC 编码器打草稿,LLM 验证,语音识别也能推测解码 WWW'26 | SS-MoE:显存墙下的 MoE 推理,Self-Speculative Decoding 怎么救场? EMNLP'23 | 不用额外模型,LLM 自己给自己加速——Self-Speculative Decoding 原理详解 ACL'24 | LayerSkip:Meta 把 Self-Speculative Decoding 从头训到尾,直接干到 2.16× 从图像到文本:Diffusion 模型原理全解——数学、结构、训练、推理一次讲清 贝叶斯优化从零推导:从「我对这个函数有个猜测」到自动调参 长音频转写慢 10 倍,99% 的 Attention 在白做功——MURMUR 如何破解这道难题 2026 | dLLM-ASR 让语音识别推理快 4.44 倍,还不掉精度 公司里那个一言不发的马尾辫大叔,现在被装进了你的 AI agent 里 SpecASR:ASR 专属 Speculative Decoding,让 LLM 语音识别快 3.79 倍 COLM'25 | PredGen:你还在说话,LLM 已经想好怎么回了 LLM agent 为什么不稳?问题可能不在模型,在 harness Meta-Harness:让 LLM 自己搜索最优 harness,模型不动,性能白涨 从零理解 ASR:音频基础、Qwen3-ASR 架构,以及离线 vs 流式推理原理 arXiv'26 | LLM Agents 让群体信念变得可编程:当 AI 开始系统性操控舆论 巴西「主权大模型」翻车:当模型可以随便融合,怎么证明它偷了你的权重? 进阶篇 | 不靠人工设计,让遗传算法自己进化出 SOTA 的 LLM 剪枝指标 说人话:一文搞懂现在火热的 LLM agent 自进化原理 ICML'26 | Transformer 真的需要三个投影矩阵吗?Q-K=V 让 KV Cache 直接砍半 UPenn & Meta | NF-CoT:当 LLM 的思维链不再是文字,而是连续概率流 arXiv'26 | 为什么你的多智能体系统越加 agent 越慢?DeLM 用去中心化解了这个矛盾 arXiv'26 | Self-Harness:让 Agent 自己改自己的 harness,pass rate 最高翻倍
LoRA fine-tune吞吐量提升1.96倍!LoRAFusion如何把内存带宽...
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