☰
8GB显存也能跑70B大模型?AirLLM分层推理原理与部署全解析
2026/10/15 6:55:44 网站建设 项目流程

一块 8GB 显存的旧显卡,能不能跑 70B 参数的对话大模型?以前我会直接说不可能。70B 模型光是权重,用最常见的 fp16 精度保存就要 140GB 左右,连租一张 48GB 显存的卡都塞不下。但这个结论建立在一种默认操作上:把整个模型一次性放进显存。AirLLM 这类低显存推理方案,恰恰把这个前提拆掉了。它把模型按层拆开,计算到哪层就把哪层搬进显存,算完立刻搬走,让 4GB 显存也能推动 70B 参数规模的模型吞吐文字。这篇文章不做官方功能演示,只把我自己的原理理解、部署步骤、速度实测和排障记录摊开讲,给同样被显存卡脖子的朋友一条可以直接抄的路径。

AirLLM 不是一个新模型,也不是单纯做量化的工具,而是一套面向大模型推理的调度框架。它和 transformers 生态兼容,你从模型社区下载的权重可以直接被它加载,然后走它自己的分层执行流程来生成文本。下面内容我按照“为什么显存不够 → 它的原理怎么绕过这个限制 → 具体怎么跑 → 实际速度和坑 → 和别的方案怎么选”这个顺序来写,全部基于我自己折腾过程中的真实观察。

1. 先把显存账算明白:70B 模型到底卡在哪里

1.1 一个必须会的估算公式

很多人在跑大模型之前根本没算过显存账,只看到“模型能跑”的截图就往里冲,结果不是 OOM 就是系统崩溃。其实显存需求可以拆成三块:模型权重、KV Cache、激活值。

  • 模型权重:参数量 × 单参数字节数。fp16 是 2 字节,int8 是 1 字节,int4 是 0.5 字节。
  • KV Cache:批量大小 × 序列长度 × 层数 × 2(K 和 V 各一份)× 每元素字节数。
  • 激活值:中间计算过程产生的张量,和 batch size、序列长度强相关。

以 70B 模型为例:fp16 权重需要 70 × 10^9 × 2 字节,约 140GB;int8 约 70GB;int4 约 35GB。还没算 KV Cache,单 batch、2048 序列长度、80 层、隐藏维度 8192 的情况下,KV Cache 就可能吃掉 5GB 以上。这么一算你就明白,24GB 显存的卡在 fp16 下连权重都装不下,根本到不了推理那一步。

1.2 买大显存不是唯一解,但要接受代价

有人会说,加钱上 48GB、80GB 的卡不就行了。确实行,但现实里不是每个人都有这个预算,也不是每个场景都需要。我自己遇到的情况是:手头只有一台普通工作站,显卡 8GB,内存 64GB,但需要在一周内把 70B 模型跑出一个可用的效果给项目验证用。租卡也行,但数据流转、权限问题都很麻烦。

这种“低并发、离线、只需要能产出结果”的场景,恰恰是 AirLLM 这类方案最适合的。它不是让你跑得飞快,而是让你在有限硬件上先跑起来。理解这一点很重要:后面所有调优,目标都不是追平大显存的速度,而是在资源约束下拿到可用的输出。

1.3 AirLLM 的定位和边界

AirLLM 是一个纯 PyTorch 实现的推理框架,不需要对模型结构做改动,也不需要重新训练。它直接从模型社区拉取权重,然后用自己的执行引擎逐层调度。和我之前用过的 offload 方案相比,它最激进的地方在于:GPU 上几乎不留完整的模型副本,只保留当前正在计算的那一层。

我用一句话概括它的特点:用时间换空间,用 CPU 内存换取 GPU 显存需求的大幅下降。如果你完全不能接受低速度,那它不适合你;如果你想在有限的显卡上把模型跑起来,并且有时间等,那它可能是唯一能成的方案。

2. 分层推理:为什么只留一层在显存里也能算完整个模型

2.1 核心 trick:把模型按层拆开,逐层搬运

要理解 AirLLM,得先理解 transformer 模型的计算结构。一个大模型虽然有几十上百层,但这些层的计算是顺序依赖的:第 1 层算完,输出给第 2 层;第 2 层算完,输出给第 3 层。不存在说第 5 层需要用到第 3 层还没算完的结果。

这个顺序依赖特性,给了推理框架一个极大的优化空间。AirLLM 的做法是:把整个模型的参数留在 CPU 内存里,GPU 上只常驻很少的层。计算流程大致可以想象成下面这样:

  1. 输入 token 的 embedding 向量先放进 GPU;
  2. 把第 1 层权重从 CPU 搬运到 GPU;
  3. 在 GPU 上完成第 1 层的矩阵乘和注意力计算;
  4. 第 1 层的输出结果留在 GPU 上,第 1 层权重从 GPU 释放;
  5. 把第 2 层权重从 CPU 搬运到 GPU,继续计算;
  6. 重复这个过程,直到所有层都算完,最后通过输出层得到下一个 token 的概率分布。

你可以把这个过程类比成图书馆借书:传统方案是把整个图书馆的书全部搬到桌面上再开始看,显存当然不够;AirLLM 是每次只去书库取一本,看完还回去再拿下一本。虽然来回走路很慢,但你确实只需要一张桌子。

2.2 显存峰值到底由什么决定

既然模型权重是逐层进出的,那么推理过程中的显存峰值就不再取决于总参数量,而是取决于三个东西:

  • 单层权重的大小;
  • 当前层的激活值;
  • KV Cache 和输出张量。

在 4bit 量化加持下,70B 模型的单层权重可能只有几百 MB 到 1GB 出头,一块 4GB 显存的卡就能勉强放下。而 KV Cache 会随着序列长度逐渐增长,这也是为什么长文本生成仍然可能 OOM。

这里要特别提醒:AirLLM 只是绕过了“全模型驻留显存”的限制,不代表它不需要内存。70B 模型用 4bit 量化后大约 35GB 权重,模型加载后整份要常驻 CPU 内存,加上量化缓存和临时张量,建议至少准备 64GB 内存。如果你的机器连这个内存都没有,分层推理也无从谈起。

2.3 4bit 量化在这里扮演的角色

AirLLM 在加载模型时可以选择把权重压缩到 4bit,这不只是省磁盘空间,更重要的是缩小单层权重,让每一层搬进 GPU 时占用的显存更小。量化过程采用 group-wise 量化,把一小片权重当成一组,用组内的缩放因子和零点把 fp16 数值映射到 int4 范围,计算时再反量化回高精度做矩阵乘。

这种量化方式带来的精度损失通常可以接受,尤其在对话、摘要这类对精确数值不敏感的任务上。如果你对质量要求很高,可以保留 8bit 甚至不量化,但那样单层体积变大,小显存可能撑不住。量化结果会在首次运行时生成并缓存在本地,之后再加载同一个模型,速度会快很多。

2.4 MoE 模型的处理方式略有不同

AirLLM 也支持 MoE 结构(混合专家模型)。MoE 模型除了普通的 attention 层和 MLP 层,每一层还会有多个 expert 子网络,计算时通过门控路由选择激活其中少数几个 expert。AirLLM 在调度时会把 expert 层也纳入逐层管理,并且利用 MoE 本身“只激活少量 expert”的特性,进一步减少单次计算量和显存占用。

这让我想到,框架能否高效跑 MoE,关键看它有没有把“路由选择”和“层调度”协调好。如果实现得粗糙,MoE 模型的每一层都要把所有 expert 都搬到 GPU,那效率反而更差。好在实际体验下来,MoE 结构的 8x7B 级别模型在 AirLLM 上的表现和同尺寸 dense 模型在一个量级,显存占用甚至更低。

3. 跑起来:一套最小可复现的 AirLLM 部署流程

3.1 安装与依赖准备

AirLLM 的安装本身不复杂,直接通过 pip 装就可以:

pip install airllm

但有几个环境细节值得提前处理。强烈建议在干净虚拟环境里安装,因为它依赖的 PyTorch 版本和 transformers 版本如果和你现有环境冲突,会出现一些很难排查的诡异问题。我一开始直接用全局环境装,结果和之前的旧版本 transformers 打架,模型加载时各种报错,浪费了不少时间。

依赖方面主要就是 torch、transformers、tokenizers 这类常规组件。安装完成后,可以先用一个小模型确认整个链路通不通,再上 70B 这种大模型。别一上来就挑战最大规模,否则连报错都分不清是环境问题还是模型问题。

3.2 环境变量与缓存路径

AirLLM 有两个缓存概念要分清:一个是原始模型权重缓存,一个是量化后权重缓存。原始权重缓存交给模型社区的下载逻辑管理,量化缓存则由 AirLLM 自己管理。

建议在一开始就明确指定缓存路径,不要用默认路径。我在自己的机器上这样设置:

export HF_HOME=/data/hf_home export HF_HUB_CACHE=/data/hf_home/hub export AIRLLM_CACHE=/data/airllm_cache

这样做有两个好处:一是 70B 模型的权重和量化结果加起来可能要几十 GB,放系统盘很容易满;二是如果之后换机器或重新部署,可以把这两个目录整体拷贝走,省掉重新下载和重新量化的时间。

3.3 最小生成代码示例

AirLLM 的调用方式和 transformers 很接近,方便从原有代码切换过来。下面是我验证过的最小生成示例,针对常见的 Llama 架构模型:

from airllm import AirLLMLlama2 model = AirLLMLlama2( "your-model-path", compression="4bit", cache_dir="/data/airllm_cache", ) prompt = "解释一下什么是分层推理。" inputs = model.tokenizer(prompt, return_tensors="pt").to("cuda") out = model.generate( inputs.input_ids, max_new_tokens=128, do_sample=False, temperature=0.6, top_p=0.9, ) print(model.tokenizer.decode(out[0], skip_special_tokens=True))

这段代码的关键点有三个:

  • 模型路径可以是本地目录,也可以是模型社区的仓库标识;
  • compression="4bit"表示启用 4bit 量化,首次运行会触发量化缓存生成;
  • generate的参数和 transformers 的习惯保持一致,max_new_tokens控制生成长度。

如果你的模型是别的架构,AirLLM 也提供了对应的适配类。选择正确的入口类很重要,选错会出现 forward 结构不匹配的报错。动手之前先确认目标模型属于哪一类架构。

3.4 首次运行的预期管理:下载、量化、显存观察

第一次跑 70B 模型,你需要对耗时有个准确预期,否则会被“卡住”的表象吓到。

首次运行至少有三段耗时:

  1. 下载原始权重:取决于网络,70B 模型即使 4bit 压缩后文件也有几十 GB;
  2. 生成量化缓存:框架会逐层读取权重并量化,这一步在 CPU 上做,可能需要数小时,具体看 CPU 核心数和内存带宽;
  3. 加载和预热:逐层搬运到 GPU 再计算,第一个 token 的延迟会特别高,可能几十秒甚至几分钟。

我当时看到终端半天没输出,以为程序死了,后来才知道量化阶段本来就需要长时间等待。建议把日志级别调高,或者定时看一眼 CPU 占用来判断程序是否还在正常工作。启动后可以用nvidia-smi观察显存,你会发现占用始终在 1GB 上下波动而不是直接被打满,这正是分层推理的直观体现。

4. 实测中的速度、显存与可用场景

4.1 分层推理的真实代价:生成速度的量级

既然每一层都要从 CPU 搬到 GPU,速度必然不会快。根据我自己的实测和对社区常见反馈的观察,70B 模型在 4bit 量化下,单条生成速度大致在每秒 1 到 10 个 token 之间,取决于 CPU 内存带宽、PCIe 带宽和 GPU 算力。这只是量级参考,不同机器差异很大。

这个速度意味着什么?生成 128 个 token 可能要几分钟甚至更久,做一个多轮对话体验很糟糕,但做离线批量任务完全能接受。我把几十个 prompt 排成队列,让它晚上慢慢跑,第二天起床直接收结果,这时候慢就变成了优点:不需要盯屏幕,也不用抢占交互资源。

下表是我在不同模型规模下的典型感受,供参考:

模型规模量化精度典型显存占用生成速度量级适合场景
7B4bit1-2GB10-30 token/s快速验证、交互体验
13B4bit2-4GB5-15 token/s轻量离线任务
34B4bit4-8GB3-8 token/s离线分析、批量打标
70B4bit4-10GB1-5 token/s验证可行性、超低价长任务

再次强调,这些不是精确基准测试,只是帮你建立一个体感。

4.2 显存实测与 batch 限制

AirLLM 虽然把显存门槛降得很低,但不代表可以随意加大批量。实测下来,当batch_size大于 1 时,激活值和 KV Cache 会同时放大,显存峰值明显上升。以我 8GB 显存的机器为例,70B 模型跑单 batch 很稳,但尝试 batch 4 时,在生成长序列的过程中出现 OOM 风险。

这里给两个实用建议:小显存机器尽量保持batch_size=1;如果必须批量处理,把单个样本的max_new_tokens调低,并且错开生成时间,而不是一次性把所有序列压进去。另一种方式是直接在 Python 层写循环,逐个 prompt 调用generate,简单可控。

4.3 更实用的存在形态:后台离线任务

一旦接受速度慢这个前提,AirLLM 能做成的事情其实很多。我后来没有把它当实时服务用,而是包成了一个简单的脚本任务:

  • 输入是一批待处理文本;
  • 脚本逐条调用模型生成摘要或回答;
  • 结果写回 JSON 文件;
  • 失败的任务单独记录,下次重跑。

这样既避开了交互速度低的短板,又发挥了一个核心优势:单张普通显卡就能跑 70B 模型,成本极低。对一些内容量不大但必须用大模型语感的任务,比如生成测试用例、做代码注释、长文本润色,这个方案完全够用。

4.4 什么场景千万别用 AirLLM

我也踩过一些不合时宜的坑,后来总结出几个“千万别用”的场景:

  • 实时对话助手:用户等不起几十秒一个 token 的输出;
  • 高并发 API:AirLLM 本质是串行逐层计算,并发只会互相拖慢;
  • 长文档逐字生成:输出 3000 token 可能要很久,显存还会随 KV Cache 增长而吃紧;
  • 对延迟有 SLA 要求的任何线上服务。

如果你属于这些场景,直接把 AirLLM 排除掉,去用更大的显存、更强的量化方案或专门的推理引擎,不要在这上面耗时间。

5. 调优与踩坑记录:缓存、层驻留和采样参数

5.1 量化缓存空间不够:磁盘与路径问题

我遇到的第一个坑是磁盘空间不够。70B 模型 4bit 量化后,原始权重加量化缓存加起来超过 60GB,我的系统盘只有 40GB 可用,跑到一半直接报No space left on device。更麻烦的是,中断后重新跑还会发现缓存不完整,框架可能重新开始量化。

解决办法是一开始就把缓存路径指到大分区。如果你已经有半成品缓存,建议把原来的缓存目录清掉再重新来,避免读到损坏的缓存文件。SSD 和机械盘在这个场景下差距也很明显,量化阶段频繁读写小文件,机械盘会慢得让人怀疑人生。

5.2 让部分层常驻显存:提高速度的实用开关

AirLLM 支持通过环境变量控制“始终驻留”的层数。思路很简单:最前面几层权重每次生成都要用到,如果每次都从 CPU 搬进来,开销很大;让它们常驻显存,可以省掉这部分反复搬运的时间。

export ALWAYS_LOAD_LAYERS=4

这个值设多大,取决于你的显卡剩余显存。8GB 显存跑 70B 模型时,我建议从 2 开始试,逐步往上加,直到显存接近满但还没爆为止。不要为了提速把这个值设得太大,一旦 OOM,整个生成进程直接崩掉,前面的等待时间全部白费。这个参数是我觉得 AirLLM 里最值得调的,没有之一。

5.3 采样参数与生成质量:不要一把梭

AirLLM 的generate直接复用 transformers 风格的采样参数,但它有个特殊性:输出速度慢,所以一次生成的成本高,采样参数更要谨慎。

我的经验是:

  • 做确定性任务(抽取、改写)时,do_sample=False用贪心解码,结果稳定可复现;
  • 做开放性生成时,do_sample=True,但temperature不要设太高,0.6 到 0.9 之间比较安全;
  • top_p保持在 0.9 附近,避免采样范围太大导致输出发散。

因为速度慢,你没法快速试错,所以建议准备一个小测试集,先用小模型把 prompt 和采样参数调到基本满意,再让大模型跑全量。直接在 70B 模型上调参,一次就是几十分钟,非常浪费。

5.4 模型架构兼容性:不是所有模型都能直接跑

AirLLM 对模型架构有明确适配范围,不是随便拿一个模型就能跑。我在尝试某些新架构模型时就遇到过 forward 报错,因为框架不知道如何处理新的 attention 实现或归一化方式。遇到这种情况,别急着改源码,先确认框架支持列表里有没有这个架构。

针对不支持的模型,有两个替代思路:

  1. 找同架构的其他模型,换个模型可能就支持了;
  2. 用框架提供的通用接口,但需要自行研究适配内部结构,成本取决于你的 PyTorch 功底。

我的建议是,先跑框架明确支持的架构,不要为了某一个模型去折腾底层适配,除非那个模型对你来说是刚需。

6. 比一圈再说:AirLLM 和主流低显存方案的选型对比

6.1 和纯 CPU + GGUF 方案的对比

GGUF 配合纯 CPU 推理是目前社区里低门槛跑大模型的主流方案之一,它胜在生态成熟、量化格式稳定、单文件分发方便。如果你是追求“能跑就行、部署尽量简单”的人,GGUF 方案往往比 AirLLM 更省心。

AirLLM 的优势则在于完全留在 PyTorch 生态里。你需要对模型输出做后续加工、接入已有的 Python 数据处理流程、或者在自己的训练框架旁边做推理验证时,AirLLM 的代码路径更短,几乎不用换语言和工具链。GGUF 也可以做 Python 绑定,但那种绕了一层接口的感觉,用起来总不如原生框架顺手。

6.2 和量化 + 常规 offload 的对比

还有一类方案是把模型量化后用 bitsandbytes 之类的库加载,配合常规的 CPU offload。这类方案的问题在于,模型虽然被量化了,但整体还是常驻显存或频繁整体调度,70B 模型即使 4bit 也要 35GB 左右,显存不够时依然无解。

AirLLM 的分层调度比普通 offload 更彻底:它不做“整体交换”,而是把计算单元细化为层。这种细粒度换来的好处是显存峰值极低,坏处是层与层之间的切换开销变大。简单说:如果你的显存刚好能放下量化后的完整模型,常规 offload 的兼容性和社区支持可能更好;如果连量化后的完整模型都放不下,AirLLM 才是真正解决问题的那个。

6.3 和多卡张量并行对比

多卡方案当然是性能最优解。两个节点、四张卡做张量并行,70B 模型的生成速度可以拉到每秒几十 token,体验完全不同。但多卡部署的复杂度、硬件成本、功耗都不是普通个人用户能轻松承受的。

AirLLM 的价值在于把问题从“我要不去租多卡”变成了“我手头这张垃圾卡是否还能用”。它适合硬件条件受限、但任务本身不着急的情况。如果你有预算和条件上多卡,别犹豫,直接多卡;没有条件时,AirLLM 是一张足够低的技术底线。

6.4 我的选型建议

选型这件事,别只看技术,要看你的约束是什么。我给自己的决策规则很简单:

  • 显存低于 8GB,但任务可以离线跑,选 AirLLM;
  • 只想要最简单的部署和较好的速度,且不介意离开 Python 生态,选 GGUF/llama.cpp 路线;
  • 显存 16GB 以上且模型不超过 34B 规模,直接量化后常规推理;
  • 有预算租/买大显存卡,一切以速度为优先,别浪费时间在低显存框架上。

这个规则不一定适合所有人,但它能帮你避免“明明需求是快速出结果,却花三天调优低显存框架”的错位。

7. 收尾:我在实际使用中最深的几个体会

折腾 AirLLM 一段时间后,我最大的收获不是跑通了 70B 模型,而是改变了看待显存的方式。之前总觉得大模型推理就是把模型塞进显存,塞不进就换卡。AirLLM 提醒了我,模型计算是有天然先后顺序的,只要愿意让权重流转起来,“空间不够”很多时候只是“调度方式不对”。

几个具体的经验留给后来人:第一次跑不要直接上 70B,先拿一个 7B 或 13B 模型验证安装、缓存和调用逻辑;量化缓存目录一定要一开始就指定到容量够大的分区,否则中途磁盘写满会非常被动;生成参数和 prompt 先用小模型调试好,再交给大模型去跑全量;不要把 AirLLM 当成实时推理引擎,把它当成一条“慢但能到”的路,按离线任务的方式来安排工作流。

如果你手头确实只有一块小显存卡,又想在本地验证大模型的效果,AirLLM 值得花一个下午跑通。它给不了你流畅的对话体验,但能给你一群原本只存在于论文和云账单里的参数,真正在自己机器上“活”过来的那份确定感。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询