LFM2.5-24B-A2B 端侧部署要看显存、量化档位决定实际占用

文章导读
端侧跑 LFM2.5-24B-A2B,先别盯着标称显存做判断。名字里的 A2B 说明推理时激活的参数量在 2B 量级,这决定的是算力和速度,不是显存;权重仍然要按总参数量加载,显存占用主要由总参数规模和量化档位决定。别人机器上能跑通的记录搬到你这里装不下,常见差异只有三处:系统实际能分给推理进程的显存少了、量化档位不是同一档、以及上下文缓存把预留吃掉。把这三项分别量出来,问题通常能定位到具体一步。
📋 目录
  1. A 先量出系统实际能分给推理进程的显存
  2. B 把量化档位换算成权重字节数
  3. C 把上下文缓存单独列成一项占用
  4. D 在配置里设上限并用日志验证
  5. E 记录一次完整的占用拆解
A A

端侧跑 LFM2.5-24B-A2B,先别盯着标称显存做判断。名字里的 A2B 说明推理时激活的参数量在 2B 量级,这决定的是算力和速度,不是显存;权重仍然要按总参数量加载,显存占用主要由总参数规模和量化档位决定。别人机器上能跑通的记录搬到你这里装不下,常见差异只有三处:系统实际能分给推理进程的显存少了、量化档位不是同一档、以及上下文缓存把预留吃掉。把这三项分别量出来,问题通常能定位到具体一步。

端侧部署 24B 级模型,显存判断要按“可用显存 − 权重字节数 − 上下文缓存 − 框架开销”逐项扣减,而不是拿标称显存对比参数量。做法是先查真实可用显存,再按量化位数换算权重字节数,然后把 KV cache 单独列项,最后在加载配置里设上限并用启动日志与显存监控核对。风险边界在于:换算值只是下限级估算,量化元数据、非量化层和碎片会让实际占用高于估算,必须留余地并以日志为准。

先量出系统实际能分给推理进程的显存

标称显存是硬件参数,可用显存是当下状态,两者之间差额来自操作系统和常驻进程。先把当前数字抓下来,再去算模型装不装得下。

# 总量、已用、剩余(单位 MiB)
nvidia-smi `--query-gpu`=memory.total,memory.used,memory.free `--format`=csv

# 谁在占显存
nvidia-smi
nvidia-smi `--query-compute-apps`=pid,process_name,used_memory `--format`=csv

# 内存与占用最高的进程,判断是否走了部分 offload
free -h
ps aux `--sort`=-%mem | head -n 15

需要从标称值里扣掉的部分,通常包括:桌面环境与显示服务(Xorg、Wayland compositor、浏览器硬件加速)、其他常驻推理进程或训练残留、CUDA context 与框架自身占用、显存分配器为对齐和碎片保留的空间。集显或统一内存架构的机器还要注意:任务管理器里看到的是共享显存,和推理框架能拿到的专用显存不是一回事,以 nvidia-smi 的专用显存读数为准。判断方法是先跑一次空载 nvidia-smi 记下基线,再启动推理进程观察增量,基线加增量才是这次部署的真实成本。

把量化档位换算成权重字节数

量化档位的作用是把“每参数多少字节”变成可计算量。通用换算是:权重字节数 ≈ 总参数量 × 每参数字节数,其中每参数字节数约等于量化位数除以 8。4bit 约 0.5 字节每参数,5bit 约 0.625,6bit 约 0.75,8bit 约 1 字节。以 24B 量级总参数、4bit 档位为例,纯权重的下限级估算落在 12GB 附近,这个数字只能用来判断“大概在什么量级”,不能当成加载峰值。

LFM2.5-24B-A2B 端侧部署要看显存、量化档位决定实际占用
  • 量化元数据:分组量化需要存 scale 和 zero-point,组越小附加数据越多,这部分不体现在“位数”里。
  • 非量化层:embedding、lm_head、部分 norm 层常被保留在更高精度,实际占用高于按位数的线性换算。
  • 对齐与填充:MoE 的专家权重按张量对齐存放,某些张量还会被复制或重整,字节数会被抬高。
  • 运行时缓冲:加载瞬时会有临时的 host 到 device 拷贝与中间张量。

所以换算结果是地板价,不是报价。配置显存上限时,在这个换算值之上留出余量,余量大小需要结合你的量化实现和框架版本用日志确认,不要预设成固定常数。

把上下文缓存单独列成一项占用

短提示能跑、长对话中途崩掉,通常是权重没变但 KV cache 在增长。KV cache 的估算方式是:字节数 ≈ 2 × 层数 × KV 头数 × head_dim × 每元素字节数 × 序列长度 × 并发序列数。系数 2 对应 key 和 value 两份;使用 GQA 时 KV 头数小于注意力头数,缓存相应变小;KV cache 量化到 8bit 或更低时,每元素字节数随之下降。

这个式子里,层数、KV 头数、head_dim 由模型结构决定,换不了;序列长度和并发数是你直接可控的变量。长对话场景下把上下文上限从较大值收到较小值,缓存的下降是线性的、可预期的。多轮对话还会因为历史累积让有效序列变长,只看单轮提示长度容易低估。建议先用估算式算出一个上限,再把 max_model_len 和最大并发数一起定下来,两者相乘才是缓存峰值。

LFM2.5-24B-A2B 端侧部署要看显存、量化档位决定实际占用

在配置里设上限并用日志验证

把估算落成配置项,字段名随框架不同需要替换,思路是给显存和上下文都设硬上限,避免运行中无限申请。

# 通用骨架,字段名按你的推理框架实际参数替换
model: LFM2.5-24B-A2B
quantization: 4bit            # 与权重文件的实际档位一致
max_model_len: 8192           # 上下文上限,直接决定 KV cache 峰值
max_num_seqs: 2               # 并发序列数,与上一项相乘
kv_cache_dtype: auto          # 缓存精度,调低可减小占用
gpu_memory_utilization: 0.85  # 相对可用显存的上限,留出碎片与临时缓冲
enable_prefix_caching: true   # 视框架支持情况开启,长系统提示场景收益明显

启动后先看日志里的加载摘要,多数框架会打印权重占用、KV cache 块数与可用块数、以及总显存预算;再把日志里的数字和第一节量到的可用显存对照,差值就是框架开销与余量。运行中另开一个终端持续观察:

LFM2.5-24B-A2B 端侧部署要看显存、量化档位决定实际占用
watch -n 1 nvidia-smi `--query-gpu`=memory.used,memory.free `--format`=csv
# 或采样记录,便于事后看峰值
nvidia-smi dmon -s m -d 1

如果启动阶段就报显存不足,问题在权重档位或 gpu_memory_utilization 设得太满,先降上限再谈压缩上下文;如果启动正常、长对话才失败,问题在 max_model_len 或并发数;如果两者都收紧了仍失败,检查是否有其他进程在同时占卡,以及是否发生了隐式的内存回退导致速度骤降。回退到内存只是让进程活下来,不解决显存不够这件事。

记录一次完整的占用拆解

把一次部署拆成表格记下来,下次换模型或换量化档位时直接套同一套方法,不用重新试错。

占用项对应参数值观察手段观察到的现象结论
标称显存显卡型号nvidia-smi 总量—仅作参照
空闲基线桌面/其他进程空载 nvidia-smi已用若干 MiB从标称值中扣除
框架开销框架版本、CUDA context加载前后显存差增量稳定存在预算里长期保留
权重总参数量、量化档位启动日志权重占用高于换算下限值以日志值替换估算值
KV cachemax_model_len、并发数、缓存精度日志块数或显存增量随序列长度线性上升通过两个参数控制峰值
失败点触发时的请求长度日志报错关键字启动成功、运行中失败归因到上下文或并发

表格里的“现象”一栏只填你亲眼在命令输出或日志里看到的内容,不要填推测值。换模型时复用这张表,把权重换算和 KV 估算重算一遍,再和日志实测对照,两三次之后就能对这类模型的显存分配形成稳定预期。需要结合具体机器环境确认的部分,比如桌面环境占用和驱动预留,每次换机器都重新量一次,不要沿用上一台的结论。