llm 量化技术综述

news/2025/3/25 19:05:41/文章来源:https://www.cnblogs.com/xwher/p/18788021

综述: LLM 量化

1. Intro

低比特量化主要是减少tensor的bit-width,可以有效减少内存以及计算需求;主要可以压缩权重, 激活值, 和梯度,使得可以在受限资源的设备上使用。

2. 低比特LLM的基础

在这一届,我们主要引入从以下三个方面讨论:

  1. low-bit 数值格式
  2. 量化粒度
  3. 动态或者静态量化

2.1 low-bit 数值格式

2.1.1 标准格式

浮点数的一般格式为:

$$X_{FPk} = (-1)s2(1.mantissa)=(-1)s2(1+\frac{d_1}{2}+\frac{d_2}{2^2}+...)$$
这里的s是符号位, p是指数的整型, bias需要应用到这个指数上;最后s p 和m的bits加起来应该等于k。

我们可以使用$EeMm$来表示对应的浮点数格式,例如float16可以表示$E5M10$, bfloat16表示为$E8M7$;因此bfloat16可以表示更大的数,但相对的数值分布更稀疏。除此之外,对于fp8也来两种主要的格式$E4M3$和$E5M2$。

NormalFloat(NF): 主要用在weight-only的量化策略

Micro scaling FP: 对tensor的sub-blocks有一个scale系数 $E8M0$ 可以进行更细粒度的量化

integer number: 将浮点数划分为 $2^k$个等间距的离散整型, 格式如下:
$$X_{INT_k} = (-1)s(d_12m+d_22{m-1}+...+d_m20)$$
对于有符号整型,我们使用$m=k-1$ 以及 $s \in {0,1}$;对于无符号,我们使用$m=k$和$s=0$

二元数: 直接抽象出值的符号;即 ${-1,1}$ 和 ${0,1}$

2.1.2 自定义格式

TODO

2.2 量化粒度

Tensor-wise, Token-wise, channel-wise, group-wise(将token以及channel划分成组), element-wise(只应用在训练权重时,在推理前,这个scale将被合并到量化权重上)

token-wise的激活值和channel-wise的权重经常一起使用;因为对应量化scale可以先进行一个计算,减少overhead

2.3 动态和静态量化

这里的两个策略主要指PTQ中的策略,我们可以看出哪些方式是需要反量化的计算,哪些则不需要:

img

动态量化: 裁剪和存储被量化的值,通常不需要输入数据,但对于weight来说可以搜索出最优的scale系数以及零点偏移$Z_w$。在推理时,激活值将作为输入进入量化模块计算出最优的scaling factor和零点偏移,之后动态地进行量化。scaling和zero point可以基于当前批次的数据实时获取。这种方法会引入额外的计算scale的复杂度。

静态量化: 需要输入数据,可以找到对于weight和activation或者weight-only的最优scale系数

3. 框架与系统支持

3.1 量化推理框架

bitsandbytes, mlc-llm, vLLM, llama.cpp, sglang...

一些主流的量化算法: GPTQ, AWQ, SmoothQuant

bit-width 支持:

  1. weight-only: 只量化权重,激活值保持fp16。这种量化的权重将会dequantize成fp16,之后执行fp16的mma运算。减少了计算设备与host之间数据传输的延迟;但是dequantize需要额外的时间。
  2. W & A: 算法量化了权重和激活值,可以直接执行低比特的乘法;所有框架都支持INT8和FP16的矩乘;受限于GPU的计算能力,只有部分硬件支持INT4 FP8的MatMul. 很少有支持不同bitwidth的框架,例如Wint4Aint8,这需要自定义的计算kernel(需要汇编的GEMV指令)。值得注意的是,如果想使用低bit的MatMul,你的硬件必须支持特定的low-bit的计算。
  3. KV cache: 与weight-only的算法类似,量化的kv cache通常在进行矩乘时,需要先将其dequant为fp16,

3.2 量化的系统支持

我们很容易会提出一个问题:量化是怎样达到加速和内存的减少的?

我们首先可以讨论模型推理时的数据传输过程:
img

  • host mem -> device mem: 对于权重来说,我们首先将每一层layer的权重从host移动到device上;量化可以减少这部分传输延迟,激活值一般都存储在device上,不需要特殊的移动。
  • off-chip -> on-chip: 将一块权重和激活值从global memory传输到片上的L2 cache和shared memory
  • shared memory -> register: 为了更快的计算,quantize和dequant操作以及matmul总是在registers上计算。
  • off-loading(register->shared memory->device memory)

3.2.1 weight-only 量化

img
weight-only和W&A量化都牵涉到a过程:

  1. 将weight量化到更低位宽,得到对应量化参数
  2. 将这些量化后的权重pack为uint32
  3. offload以及存进host mem

注意weight-only减少了从host mem到on-chip mem的传输时间,但引入了额外的dequant开销。我们甚至没有必要设计一个线性的从低比特数到真实值的满射;换句话说,我们可以将整数映射为任意的浮点数,通过lookup table的机制。

3.2.2 W & A 量化

img
我们需要执行额外的将激活值从fp16量化为更低bit的整型;在计算完成后,将INT32转为FP16。

有两种自定义的设计:

  1. faster quant & dequant
  2. faster matmul kernel: gemv相比gemm对于适配不同位宽具有更高的灵活性和效率;通过将一些矩阵和向量的乘法进行组合可以得到最终的结果矩阵。

3.2.3 KV cache 量化

img

有三种技术:

  1. quant to lower bitwidth:
  2. quantizing window: 推迟量化发生的时机
  3. 跳过Knew的dequant: 先将其与先前dequant的kv进行concat,防止丢失信息
  4. 优化outliers

3.2.4 quant和dequant

Floating-point quant: 将更高bit的浮点数quant为低bit,实际上是mantissa bit的裁剪。我们可以总结出以下的流程:

  1. scale。 目标占据更少的bit,表示范围将会大大减小;这个scaling可以通过学习或者裁剪来预先获取
  2. 检查上溢和下溢。检查source是否overflow了目标的表示范围;如果是,直接返回最大或最小。
  3. 拷贝和round。如果值没有overflow或underflow,我们可以直接round

float-point dequant: 直接0️⃣填充

Int quant:
$$X_{INT_k}=clamp(round(\frac{X_{FP}}{s})+z, q^{min}, q^{max})$$
其中$s$可以被初始化为$\frac{q{max}-q{min}}{X{max}_{FP}-X_{FP}}$.

对于系统支持,很多框架都应用了marlin quant作为基础过程。

Int dequant: $$X_{FP}=s(X_{INT_x}-z)$$。可以通过某个算法找到最优的s

二元量化

4. LLM training的高效量化策略

4.1 低比特训练

FP16 训练: 通常使用BF16进行模型训练,然而需要特定的硬件支持;对于老硬件,我们使用fp16进行加速,但是有under/overflow的风险。

fp8 traning: 利用transformer engine;需要对每个fp8的tensor都有一个scaling factor,注意需要延迟获取。

4.2 PEFT的量化策略

QLora:

5. LLM 推理的高效量化策略

TODO

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/904369.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Top 出海 AI 公司招技术!HIX.AI Pollo.ai | 深圳

HIX.AI & Pollo.ai 招聘高级海外 AI 产品经理 (25-45K) 岗位职责:负责Web 端海外 AI 产品的规划与策划,负责产品需求分析及原型设计,并制定方案推动产品研发落地; 进行产品/竞品调研,了解用户需求,分析、发现需求本质,并给出对应的解决方案; 有效对接开发、测试、运…

2、切片

一:字符串的下标(索引)--重点 ​ Ⅰ:字符串的特性,被称为下标或者 sequence(序列) ​ Ⅱ:一个序列。若干元素组成 ​ Ⅲ:字符串的下标从0开始》标记每个元素的位置,用来获取元素》从左到右,从0开始> a[0],a[1] ,a[3]》可以用正数表示,也可以用负数表示》最…

WEBGL 学习使用代码

目录杂七杂八第一节 绘制出了一个点第二节 动态传递点数据第三节 缓冲区和画线第四节 彩色线段第五节 单个 buffer 渲染颜色第六节 抽离代码 & 画彩色三角形第七节 图元的七种绘制方式第八节 uniform 传值变换数据第九节 旋转矩阵三角函数矩阵的计算推导代码实现第十节 线框…

Kettle 版本这么多,到底该怎么选?

Kettle(Pentaho Data Integration)作为一款功能强大的开源 ETL(Extract, Transform, Load,即数据抽取、转换和加载)工具,拥有众多版本,这让许多用户在选择时犯了难。 1、提出问题 经常有群友提出使用kettle版本的问题,如下图所示:2、kettle版本 有许多的的历史版本,…

C++实验二

实验一#include <stdio.h>#include <stdlib.h>#include <time.h>#define N 5int main() {int number;int i;srand(time(0)); // 以当前系统时间作为随机种子for(i = 0; i < N; ++i) {number = rand() % 100 + 1;printf("20490042%04d\n", n…

ESP32 Audino 驱动12864点阵屏 自定义中文字库

一.安装u8g2 #include <Arduino.h> #include <U8g2lib.h>U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remappingvoid setup(void) {u8g2.begin();u8g2.enableU…

Linux 离线安装 lz4

前言:本文操作是在 CentOS-7 下执行的,不确定在其他 Linux 发布版是否能同样正常执行。1、检查前置依赖组件在安装 lz4 之前,需要确认已安装了相关依赖组件: gcc 。 rpm -qa | grep gcc前置依赖组件的具体离线安装方法请参考:CentOS-7离线安装gcc 2、下载lz4安装包 官方下…

sql语句把图片存入数据库

这是一个小的练习,目的是把图片以二进制字符串形式存入sql数据库表中,后续练习尝试在WINCC把其还原成图片。 在以前的数据库MyDB中新建一个数据表,有四个字段: imageID 类型为bigint,作为标识符,自增1 mydatetime 日期事件类型 imagename varchar(100)数据类型 imagedata…

FSRCNN:加速超分辨率卷积神经网络

作为一种成功的图像超分辨率 (SR) 深度模型,超分辨率卷积神经网络 (SRCNN) 在速度和恢复质量方面都表现出优于以往手工制作模型的性能。然而,高计算成本仍然阻碍了它需要实时性能 (24 fps) 的实际使用。在本文中,我们旨在加速当前的 SRCNN,并提出一种紧凑的沙漏形 CN…

GNSS测量实习

实 习 报 告学院:建筑工程与空间信息学院 专业:地理信息科学 实习性质:校内实习 实习单位:建筑工程与空间信息学院 指导教师:冯建迪目录 一、实习的性质和目的要求 二、实习的任务和内容 三、静态测量 3.1 静态测量简介 3.2作业流程 3.3注意事项 3.4 GPS 控制网设计…