九源开源技术周 01| InfiniLoader:用内存缓存加速模型加载

在调试推理引擎时,我们经常会碰到这样的情况:刚改了几行代码,花十来秒跑一次验证就能知道结果,却得先等几分钟,甚至更久,模型才能加载到 GPU 上。查精度问题、调整算子实现,都要这样来回启动好几遍。
为什么需要 InfiniLoader?
连续使用同一个模型时,Linux 的 page cache 通常能加快后续读取。但实际调试中,两次运行之间还要改代码、重新编译,有时忙了半小时甚至一小时才回头验证。如果这期间编译或其他任务带来内存压力,之前模型文件的缓存就可能已经被回收了一部分。
轮流测试几个大模型时也一样。主机内存不够宽裕时,加载下一个模型就可能挤掉上一个模型的缓存。等切回来,又得从存储补读。
InfiniLoader 就是我们为此做的一个小工具:先把模型文件缓存到主机内存,由独立的后台进程保留。后续启动直接使用这份缓存,要提前准备哪些模型、保留多久,都可以自己决定。
一条命令先把模型文件准备好
比如,已经下载到本地的 Qwen3-8B,用这一条命令就能建立内存缓存:
iloader start /models/Qwen3-8B --name qwen8b
qwen8b 是这份缓存的名字。准备好后,执行 iloader view qwen8b,就能拿到一个可以直接访问的模型目录。这个目录入口叫作 view,里面仍按原来的结构组织权重、配置和 tokenizer 文件,推理引擎可以像读取普通模型目录一样使用它。
如果还要切到 Qwen3-14B,可以再执行:
iloader start /models/Qwen3-14B --name qwen14b
这样两份缓存就能同时保留,需要哪个模型,就分别用 iloader view qwen 或 iloader view qwen14b 取路径。
⚠️ 同时放几个模型,就得有装得下这些文件的主机内存,同时也要给推理框架留出一定空间。
给 InfiniLM 换一个模型路径
先看九源的推理引擎 InfiniLM。下面是一组在 InfiniLM 仓库目录中运行的完整启动命令(以 NVIDIA GPU 为例)。使用缓存时,只需要换掉模型路径,其他参数照旧:
# 原来从模型目录加载
python3 python/infinilm/server/inference_server.py \
--model /models/Qwen3-8B --device nvidia --tp 1 \
--host 127.0.0.1 --port 8000
# 改为读取 InfiniLoader 的缓存
python3 python/infinilm/server/inference_server.py \
--model "$(iloader view qwen)" --device nvidia --tp 1 \
--host 127.0.0.1 --port 8000
后面仍由 InfiniLM 按原来的流程读取权重、运行模型。示例沿用默认关闭空闲回收的设置。调试时可以只重启引擎,让缓存进程继续保留文件,等读取任务结束后再释放。
vLLM、SGLang 也可以按同样方式接入,具体兼容性取决于所用版本的加载器是否支持这一文件接口。以 vLLM 为例,只需把模型路径换掉:
# 原来从模型目录加载
vllm serve /models/Qwen3-8B --tensor-parallel-size 1
# 改为读取 InfiniLoader 的缓存
vllm serve "$(iloader view qwen)" --tensor-parallel-size 1
SGLang 和其他兼容普通文件接口的开源框架、评测脚本,也可以使用这份缓存。做不同框架或代码版本的对比时,模型文件没变,各组实验就能继续读取已经准备好的文件。
改代码的时候就可以开始加载
有了独立的缓存进程,加载模型也不用非得等到代码改完再开始。
准备调试某个模型时,先在终端执行 iloader start /models/Qwen3-8B --name qwen,让文件开始读取,你照常改代码。等代码改好、缓存也准备好了,再启动验证,从原始存储读文件这一步就已经提前完成了。
这里预载的是主机内存中的模型文件,不占用 GPU 显存。所以连续评测多个模型时,也可以趁模型 A 还在 GPU 上计算,先把下一轮要用的模型 B 预载起来。只要主机内存和 I/O 还有余量,两件事就可以同时进行,等 GPU 空出来再启动 B。
省下的是哪段等待?
拿 100 GB 的模型权重举个例子:按 1 GB/s 的有效读取带宽估算,仅把文件读出来就要 100 秒左右。
InfiniLoader 处理的是这部分原始存储读取,可以提前做,也可以在后续启动时复用缓存。权重解析、张量创建和传到 GPU 等工作,仍然由推理引擎完成。
⚠️第一次准备缓存也要花时间,并且会占用主机内存。如果系统页缓存本来就很充分,额外收益可能不大;内存紧张到发生 swap 时,缓存读取也会受影响。这些成本都算进去,才能知道自己的调试和评测流程实际少等了多久。
后续还可以做些什么
文件能提前准备、跨进程复用以后,还有几件事值得继续做:
1. 多机只加载各自需要的权重
多机运行一个大模型时,如果每台服务器都先缓存整份权重,主机内存会用得很快。更合适的做法是按张量并行和流水线并行(TP/PP)的布局,让每台机器只准备本机要用的分片及必要副本。
InfiniLoader 已经有实验性的显式 TP/PP 分片导出能力,目前还需要自己给出切分规则、把文件分发到各节点,并配合相应的模型适配器读取。后续可以把布局准备、分片分发和节点缓存启动连起来,逐步做成自动流程。换一种并行布局时,也要考虑分片是否需要重新准备。
2. 让权重继续留在 GPU 里
现在文件准备好以后,权重还要从主机内存搬到 GPU。后续可以探索让 GPU 权重独立于推理进程驻留,引擎重启后继续复用,进一步减少重复传输。
仓库已有实验性的 GPU 专家池,可以在同一进程内保留选中的 MoE 专家;要扩展成跨推理进程的权重缓存,还需要引擎接入和显存生命周期管理。显存被缓存占住后,留给其他任务的空间也会减少,保留哪些权重需要有所取舍。
3. 让预加载跟上任务顺序
前面说的“模型 A 还在跑,先准备模型 B”,现在可以手动安排。后续可以与评测脚本或任务队列对接,提前知道下一轮要用哪个模型,在内存和 I/O 允许时自动预载。再结合已有的本地磁盘缓存,让近期要用的模型留在内存,暂时不用的模型先放在本地盘,减少每轮实验前手动准备的工作。
一组小实验
下面用 Qwen3-8B 做一组对比,GPU 为 L20,精度为 BF16,推理框架使用 Transformers。三种场景都计时到首个 token:
| 场景 | 普通 NFS 加载(秒) | InfiniLoader(秒) |
|---|---|---|
| 冷启动 | 75.69 | 60.95 |
| 热启动 | 6.56 | 6.38 |
| 受控内存回收后启动 | 60.17 | 6.73 |
- 冷启动: InfiniLoader 的 60.95 秒已包含 54.53 秒首次预载,比普通 NFS 的 75.69 秒少了约 15 秒。
- 热启动: 两边分别是 6.56 秒和 6.38 秒,差别很小。连续使用同一个模型时,系统页缓存确实已经帮了不少忙。
- 受控内存回收后启动(差异最大): 这一轮通过隔离的内存压力做受控回收,普通加载对应的模型文件页驻留率从 100% 降到 0%,InfiniLoader 的内存缓存保持 100%。随后,普通方式用了 60.17 秒,InfiniLoader 用了 6.73 秒,前者耗时约为后者的 8.9 倍。
📊 实验结论
从约一分钟缩短到约七秒,代价是为缓存保留约 16.4 GB 主机内存。
*注:这里测的是受控回收条件下的再次启动,还不能直接当成真实多模型自然轮换的结果。六次生成的输出一致。这次测试直接调用核心缓存 API,没有重新验证命令行守护进程的生命周期。后续可以再补上真实多模型轮测,以及从改代码、预载到启动验证的完整流程测试。
🔗 相关链接
- 开源仓库: https://github.com/InfiniTensor/InfiniLoader
- 中文说明: https://github.com/InfiniTensor/InfiniLoader/blob/master/README.zh-CN.md
- 使用指南: https://github.com/InfiniTensor/InfiniLoader/blob/master/docs/usage.zh-CN.md
- 分布式与 GPU 实验接口: https://github.com/InfiniTensor/InfiniLoader/blob/master/docs/usage.zh-CN.md
关注与交流

