01 · 每个任务复制一整份模型,代价在哪里
多个LoRA适配器可以来自同一基座。若为每个适配器常驻一份完整合并模型,计算路径简单,但重复保存基座;若共享基座,每个请求只需补上自己的低秩增量,却增加分支计算、调度和适配器管理。
固定单适配器部署与多适配器混合服务是两个场景。不能把“LoRA可合并后无额外分支”推广为“一个共享多LoRA实例完全没有额外开销”。
02 · 四个请求如何共享一次大矩阵调用
设本轮输入行来自请求P/Q/R/S,适配器分别为A/B/A/基座。共享基座路径对整批做Ybase=XWᵀ;低秩路径按各行身份读取对应A/B矩阵,无适配器行的增量为零。这里把LoRA两矩阵记作Down/Up,避免与适配器名称A/B混淆。
输入行序:P(A), Q(B), R(A), S(无)
共享基座:全部行 → W → Ybase
适配器A分组:[P,R] → DownA → UpA → 加到行0/2
适配器B分组:[Q] → DownB → UpB → 加到行1
S只保留基座输出;最终仍按P/Q/R/S返回按适配器聚集行能把许多小调用组织起来,也可通过索引直接读取原行。不同rank、目标模块、dtype与布局可能需要不同任务或工作块;Grouped/分段内核不是把各适配器权重加成同一份。
依据:S-LoRA · 多适配器分页与异构批处理原始论文 ↗ · vLLM · 混合LoRA请求及服务配置(latest) ↗
03 · 分组之后,行身份和rank都要保留
自设单层din=dout=4:适配器A rank1,B rank2,输入调用数为2/1,另1行不启用。A分组有效低秩工作为2×2×1×(4+4)=32 FLOP,B为2×1×2×(4+4)=32 FLOP,总64 FLOP。
若把全部4行都按max-rank2分配稠密分支坐标,相应预算为128 FLOP;它是粗糙统一补齐方案,不代表任何引擎一定如此执行。原行、适配器ID、版本、rank/scale、偏移和回写位置都应一致。
分组还原后,增量加给哪个请求?
P/Q/R/S原行0/1/2/3,对应A/B/A/无;分组顺序P/R/Q。A rank1,din=dout=4;仅计低秩分支数学FLOP,忽略启动、重排和硬件tile边界。把A/B顺序换掉,或者把分组输出连续写回前几行,会给请求错误的增量。即使模型不报shape错误,语义也已经错了。连续批处理退出/加入请求时,这些映射需要随活跃batch正确更新。
04 · 固定合并省分支,代价是权重身份改变
标准LoRA,推理dropout关闭:
Wmerged_A = Wbase + scaleA * UpA @ DownA
y = Wmerged_A @ x
# 与Wbase@x + scaleA*UpA@(DownA@x)数学等价。
# 只对适配器A成立,不会自动代表B。若有N个固定适配器,每个独立合并模型约需N份基座大小的权重;共享动态模式约为1份基座加常驻适配器总量,另计workspace与KV。不要把矩阵合并与把多个任务适配器加权成新模型混同,后者改变服务对象并需质量验证。
PEFT提供merge_and_unload与可保留适配器管理的合并路径;应使用返回模型并核对支持范围。量化权重、DoRA等变体和特殊模块不一定满足本页最简单的公式或导出条件。
05 · 低位基座合并后,数值可能再次改变
若基座来自量化码,逻辑矩阵是按尺度/码本还原的W。可先按支持流程还原、加LoRA增量,再导出或重新量化;重新量化会引入额外误差,并可能改变最终dtype与容量。
把浮点ΔW直接加到整数码上,忽略尺度或NF4码本,不是在同一个数值空间。验收应比较动态分支、合并浮点与最终量化模型,不能只验证W+sBA这一步。
06 · 适配器按需加载,也占容量与带宽
设某个适配器覆盖32层,每层2个4096×4096投影,rank16,参数各2B:每矩阵适配器0.25 MiB,总16 MiB。常驻100个就是1600 MiB原始参数;不含其他模块、尺度、映射、暂存和KV。
可以把冷适配器放主机,热点留设备,按当前批次需求预取;先确保权重搬完再执行,最后一个读者结束后才能淘汰或覆盖槽位。S-LoRA是统一分页和异构适配器批处理的研究入口,不能把论文系统名当任何框架默认行为。
每批允许的适配器数、rank上限和CPU/设备缓存预算是不同配置。减少混合适配器种类可能改善小分支利用,却增加等待;批量越大不一定适合低延迟请求。
依据:S-LoRA · 多适配器分页与异构批处理原始论文 ↗ · vLLM · 混合LoRA请求及服务配置(latest) ↗
07 · KV与结果缓存必须识别适配器
适配器可能改变某层的隐藏向量、K/V或后续层输入。即使token前缀相同,不同适配器的历史KV也一般不能互换。缓存身份应纳入影响计算的基座/适配器版本、tokenizer和位置等兼容信息。
如果能证明某段缓存位于所有适配变化之前,可以设计受限共享;不能用这个特例允许整段KV跨任意适配器复用。适配器热更新时,旧请求及异步任务要继续引用正确版本,避免ID相同而权重已经被覆盖。
请求绑定不可变的计算身份
加载/确认对应版本设备权重已就绪
构造本轮输入行→适配器/缓存映射
执行共享基座与适配分支,按原行合并
完成后释放引用;只有无读者才允许淘汰
# 取消请求也必须处理未完成的异步访问。08 · 小脚本比较三种执行与错误路由
下载脚本比较逐请求动态LoRA、按适配器分组和每适配器合并权重的输出,包含rank1/rank2及不启用分支的行。另展示错选适配器的反例、不同适配器的简化Key不兼容,以及读者仍活跃时禁止淘汰的生命周期模型。CPU模型不实现完整服务引擎。
用同一组请求建立逐请求正确输出
核对混合batch的row、ID、rank、scale与版本
比较动态、分组与允许的固定合并
测试加载/取消/更新期间引用和缓存兼容
测基座、分支、重排、加载、排队的总路径
# 基座权重共享不意味着不同请求的激活和KV共享。09 · 收益要和加载及排队一起算
| 目标 | 验收内容 |
|---|---|
| 正确性 | 适配器身份、输出还原、量化合并误差、版本和KV兼容。 |
| 容量 | 共享基座、CPU/设备适配器、KV、重排与工作区峰值。 |
| 吞吐 | 相同请求混合下,分支任务大小、启动、加载命中和总tokens/s。 |
| 延迟 | 冷/热适配器首token,排队、切换和生成间隔。 |
不同平台的混合适配器内核与加载支持需要分别核查;CUDA异构batch实现不自动成为NPU能力。可先保持逐请求语义,再逐项比较分组、常驻与合并策略。
依据:vLLM Ascend · 支持功能矩阵(main) ↗
- 为什么一份Wmerged_A不能给B请求使用?
- 基座路径可以合批,为什么KV不能无条件跨适配器共享?
- 淘汰适配器为什么要等最后一个设备读者完成?
流程位置与关联方法
这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。
资料与核查范围
原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-10。引用 main / latest 文档时,实际接口以安装版本为准。
- LoRA · 低秩适配原始论文 ↗
- S-LoRA · 多适配器分页与异构批处理原始论文 ↗
- Hugging Face PEFT 0.21.0 · LoRA参数、变体与合并 ↗
- Hugging Face PEFT · 量化基座微调 ↗
- vLLM · 混合LoRA请求及服务配置(latest) ↗
- QLoRA · 量化基座微调原始论文 ↗
- Transformers · How Caching Works ↗
- vLLM Ascend · 支持功能矩阵(main) ↗
代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。