2GB 设备的小模型容量账:哪些页共享,哪些随上下文增长
“量化权重只有1GB,所以2GB设备还能再开一个会话。”这个判断漏掉的通常不是某个神奇内核参数,而是所有权和计量口径。
同一份文件页可能被多个进程共享,KV缓存常随上下文和并发增加,工作区又不一定按会话线性增长。把两个进程的RSS相加,会重复计算部分共享页;只看权重文件大小,又会漏掉运行时和系统开销。
先统一单位,再讨论装不装得下
2GB按十进制是2,000,000,000字节;2GiB是2,147,483,648字节。实际可供用户态使用的量还受固件、内核、设备预留等影响。采购单、/proc/meminfo和测试脚本必须注明自己采用哪个口径。
| 内存对象 | 主要变化来源 | 怎样核查 |
|---|---|---|
| 文件映射权重 | 文件版本、触页与后端复制 | 文件大小、映射、PSS |
| 匿名区 | 解码、量化转换、运行时分配 | smaps_rollup与分配记录 |
| KV缓存 | 层数、KV头、上下文、数据类型、并发 | 模型配置与运行时统计 |
| 工作区 | 后端、批大小、算子与并行策略 | 峰值与阶段采样 |
| 系统及其他业务 | 驱动、服务、页缓存和负载 | 整机与cgroup指标交叉检查 |
mmap建立映射,不是给模型开一条直达计算单元的专用通道。同一文件的干净页可被共享,后端转换、写时复制和设备缓冲区却可能另占内存。mmap(2)
图中的两个进程共享权重,是一种条件成立时的布局。KV和工作区在图中画成私有块,用来提醒我们别把权重共享推成“全部内存都共享”;具体运行时仍可能有自己的共享或复用策略。
给KV缓存写一个可检查的算式
对使用常规K、V缓存、各层维度相同且缓存完整上下文的注意力模型,可以先估算:
KV字节 ≈ 2 × 层数 × KV头数 × 每头维度 × 缓存token数 × 每元素字节数。
这里用KV头数,而不是笼统代入查询头数。量化缓存、滑动窗口、混合架构、块元数据、对齐和分配策略都会让实际值偏离这个简式。它不是所有模型的通用内存公式。
下面脚本保存成capacity.py,只做整数预算,不加载模型:
def kv_bytes(layers, kv_heads, head_dim, context, bytes_per_value): values = (layers, kv_heads, head_dim, context, bytes_per_value) if not all(type(x) is int and x > 0 for x in values): raise ValueError("positive integer dimensions required") return 2 * layers * kv_heads * head_dim * context * bytes_per_value def capacity(total, system, weights, kv, workspace): if min(total, system, weights, kv, workspace) < 0 or kv + workspace == 0: raise ValueError("invalid budget") return max(0, (total - system - weights) // (kv + workspace)) if __name__ == "__main__": # Hypothetical standard attention cache. Not a model benchmark. kv = kv_bytes(24, 4, 64, 1024, 2) print("hypothetical KV bytes:", kv) print("hypothetical KV MiB:", kv / 2**20) print("contexts under assumed budget:", capacity(2048, 384, 1024, kv // 2**20, 96))示例在Python 3.9.6上运行python3 capacity.py,假设24层、4个KV头、每头64维、1024 token和每元素2字节,得到25,165,824字节,也就是24MiB。再假定总量2048MiB、系统保留384MiB、共享权重1024MiB、每会话工作区96MiB,算式给出5份上下文。
这些都是脚本里公开写出的假设输入。“5”不是某块2GB板卡的实测并发,24MiB也不是某个已命名模型的实际缓存占用。该预算还把工作区按会话计入,是简化的保守口径;运行时若共享工作区或有额外固定开销,必须重新建账。
容量验证只回答容量问题
后续上板先固定模型哈希、量化、运行时commit、上下文和并发。单请求运行后,再逐步增加并发,保留启动失败、分配失败和退出码,不能只展示成功的一次。
测量至少保留进程PSS、memory.current、memory.stat和整机MemAvailable。这些指标的归属与层级不同,应解释差异,不能互相替代。Free与MemAvailable也不应直接相加当成额外可用量。cgroup v2文档
若预算不够,先拒绝启动或减少并发。zram使用真实内存存放压缩数据,它的逻辑容量不是凭空增加的RAM;量化权重也不能预设固定压缩比。zram文档
本文没有2GB设备、模型吞吐或长稳测试结果。容量账算清以后,延迟、温升、持续运行与恢复能力仍需另验;不能用“能装进去”代替“能交付”。