ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

大模型本地部署神器的瘦身进阶原理,就这两招?

大模型本地部署神器的瘦身进阶原理,就这两招? 温馨提示另有配套视频版附带图解演示观感不同欢迎到各大视频平台搜索同名标题或【蛋先生说识】开场丹尼尔蛋兄本地跑大模型有啥好工具推荐不蛋先生Ollama 啊装上就能用丹尼尔跟你聊多了忍不住想问——它的实现原理是什么蛋先生哈哈底层靠的是 llama.cppOllama 只是站在它肩膀上的众多应用之一丹尼尔llama.cpp上次听你讲量化原理可在各平台搜索《你瘦不下来但大模型可以量化原理了解一下》的时候好像听过这个词蛋先生没错本地算力有限不量化根本跑不动。llama.cpp 在量化算法优化这块上还是下了不少功夫的丹尼尔量化原理我是懂了个大概那今天就跟我讲讲 llama.cpp 在量化上的优化呗性价比之王Q4_K_M蛋先生llama.cpp 的量化类型有不少有 I-QuantsK-Quants 等等。而 K-Quants 又可分为 Q4_K_MQ5_K_M 等等丹尼尔等等等等。。。你就挑一个最有代表性的讲就好了我听不了这么多的名词蛋先生作为技术男性价比肯定是首位。那就 Q4_K_M 吧用得最多官方也默认推荐丹尼尔Q4_K_M 各表示啥蛋先生Q4 表示使用 4 位来量化权重K 表示使用 K-Quant 优化算法类型M 表示中等平衡核心优化一混合精度丹尼尔哦那具体都优化了啥蛋先生核心就两点。第一点混合精度Mixed Precision。大模型是一层一层摞起来的深度学习里深度俩字就是这么来的。如果每一层都用 INT4那就是吃大锅饭——一刀切。不管哪层更重要统统一个待遇丹尼尔咦就有点像埋没人才的意思蛋先生对喽大锅饭养不出尖子生好钢得用在刀刃上丹尼尔那怎么区别对待蛋先生给重要层的一些关键张量多分点精度比如 5 位或 6 位丹尼尔张量是啥蛋先生我就简单科普一下说多就扯远了。张量Tensor是数值和数组的通用叫法。数值就是标量比如1.11维数组就是向量比如[1.1, 2.2, 3.3]、2维数组就是矩阵比如[[$1.1, 2.2], [3.3, 4.4]]等丹尼尔大概明白了。那大模型哪些层是更重要的然后这些层的哪些张量是更关键的蛋先生┐(´-)┌ 这是另一个深度话题了就不展开了。顺嘴提一句 - 现在大模型基本都是 Transformer 架构注意力层Attention Layer肯定算重要层之一丹尼尔行所以结论是大部分层权重 4 位像注意力层这种重要层的一些关键张量就给更多位精度比如 5 位或 6 位这就是混合精度蛋先生总结到位核心优化二两级分组双重量化丹尼尔那第二点呢蛋先生第二点更硬核——两级分组加双重量化丹尼尔等等我觉得你有必要说下分组是怎么肥事先蛋先生上次聊量化再次提示可在各平台搜索《你瘦不下来但大模型可以量化原理了解一下》的时候结尾有提到。简单理解就是把所有权重分成多个分组进行量化丹尼尔哦结尾啊好像有点印象了。算了我等会再去翻翻。那两级怎么讲蛋先生把分好的分组内部再进行一次分组不就两级了嘛 (˘ᵕ˘)第一次分组的组叫超级块Super-block每个超级块含 256 个权重参数[ w0 w1 w2 ... w255 ] [ w256 w257 ... w511 ] [ ... ] └──── 超级块 1 ─────┘ └──── 超级块 2 ─────┘ 256 个权重参数 256 个权重参数然后再在每个超级块内部再进行一次分组分成 8 个子块每个子块包含 32 个权重参数└─────────────────── 超级块256 个权重参数────────────────────┘ └──── 子块 1 ─────┘ └──── ... ─────┘ └──── 子块 8 ─────┘ 32 个权重参数 32 个权重参数 32 个权重参数丹尼尔哦听是听懂了但为什么要这么干呢直接按 32 个权重参数一组一次分了不就完事了吗[ w0 w1 ... w31 ] [ w32 ... w63 ] [ ... ] [ w480 ... w511 ] └──── 分组 1 ────┘ └──── 分组 2 ────┘ └──── 分组 16 ────┘ 32 个权重参数 32 个权重参数 32 个权重参数蛋先生这就又得说回量化原理了。不太熟悉量化原理的同学你暂且可以用对称加密来简单理解提示不一样的东西哈只是借用了把 A 转成 B把 B 转回 A 这一相同特性来说明而已。对称加密是不是得有一个密钥来解密丹尼尔当然蛋先生在量化中密钥就是缩放因子scale和偏移量min - 仅非对称量化需要。“密钥”是需要存储的我们先来算一笔帐假设有 512 个权重参数按每 32 个权重参数一组分一共有 16 个组每个组要记两个“密钥”信息假设都用 FP16那么所有密钥得用FP16 * 2 * 16 32 * 2 * 64 512 位而所有的权重参数如果按 INT 量化也就4 * 512 位丹尼尔啊模型不就又又又胖回去了蛋先生对所以得怎么处理呢丹尼尔难道是把“密钥”也压量缩化了蛋先生猜对了这就是双重量化。它不直接用 FP16 存子块的“密钥”而是把它们再量化成 6-bit 整数。但我们知道对“权重参数”量化需要“权重参数密钥”那对“权重参数密钥”量化就需要“权重参数密钥的密钥”丹尼尔好绕口蛋先生哈哈那把它放在哪好呢肯定是往上一级放是吧。那没有上一级怎么办那就创造上一级也就两级分组咯。结果就是每个超级块额外存两个高精度 FP16 的权重参数密钥的密钥用来把那些 6-bit 的 “权重参数密钥” 还原回来。既保精度又压体积丹尼尔这样能省多少蛋先生用刚刚的示例再来算一笔帐512 个权重参数按 256 个权重参数进行一级分组一共有 2 个超级块它们存放的所有“权重参数密钥的密钥”大小为FP16 * 2 * 2 64 位每个超级块按 32 个权重参数一组一组分同样一共有256 / 32 * 2 16 个子块所有子块的“权重参数密钥”大小为6 * 2 * 16 192 位“密钥”总共消耗64 192 256 位对比只进行一级分组 512 位的消耗足足节省了一半丹尼尔我捋一下……超级块存 2 个 FP16子块的只存 2 个 6-bit靠超级块这两把钥匙还原。是这个意思吧蛋先生正是。总结一下子块分组小32 个精度保住了双重量化又压住了元数据的体积膨胀。这就是平衡的艺术——在精度和体积之间找到那个性价比天花板丹尼尔多么精巧的设计啊服了写在最后亲们都到这了要不点赞 / 收藏 / 关注支持下呗 o(▽)
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进