
大模型的量化我们前期也探讨了基础概念和实践原理,针对CPU的量化流程做了通俗易懂的基础说明,但实际应用场景往往是需要GPU的落地实践,随着大模型参数规模突破千亿级别,存储大、显存高、速度慢、成本贵成为制约其本地化部署的四大核心痛点。量化技术作为解决这些问题的核心途径,通过将模型高精度浮点数权重映射为低比特整数,在牺牲轻微精度的前提下,实现存储、显存和计算效率的倍数级提升。
在众多量化方案中,INT4 和 INT8 是应用最广泛的两种低比特量化技术。INT8 以“精度稳定、生态成熟”著称,INT4 则凭借“极致压缩、速度领先”成为边缘设备和消费级硬件的首选。今天我们重点从基础理论、核心差异、选型策略、场景适配、代码实现五个维度,全面拆解 INT4 与 INT8 量化技术,进一步的彻底搞懂两种方案的适用场景和落地方法。

量化的核心是“缩放 + 映射”:将模型中原本用 32 位浮点数(FP32)存储的权重,通过数学变换映射到有限的整数范围内,推理时再通过反量化还原为浮点数。这个过程的本质是用“可接受的精度损失”换取“极致的部署效率”。
压缩比的直观数学说明:
实际存储示例:
这里我先进行初步了解,了解公式和范围的意义,对比下一小结的详细计算过程,斟酌思考,此处需要深度思考,建议多看几遍反复理解,强化min_val、max_val、q_min、q_max代表的意义;
假设原始权重的取值范围为 [min_val, max_val],目标整数范围为 [q_min, q_max],则:
2.1 计算缩放因子
2.2 计算零点
2.3 量化公式(FP32 → 整数)
2.4 反量化公式(整数 → FP32)
量化的关键是计算两个核心参数:缩放因子(scale) 和 零点(zero_point)。我们用结合体重秤应用的生活场景,通俗解释缩放因子(scale)和零点(zero_point)的作用,通俗易懂。
我们通过经过精度不同的秤来做个类比:
现在要把电子秤的精确体重值,转换为弹簧秤的整数刻度值,这就是量化的过程,而scale和zero_point就是完成这个转换的核心因素。
我们以“把电子秤的体重值(0~200kg)转换为 INT8 便携秤的刻度(-128~127)”为例,讲透两个参数的作用:
缩放因子实际就是相当于体重秤的“刻度换算比例”,把原始数据的大范围,等比例“压缩”到量化后整数的小范围。
3.1.1 INT4 缩放
3.1.1 INT8 缩放
零点实际就是“秤的调零基准”,相当于给弹簧秤调零,处理原始数据范围不是从 0 开始的情况,确保量化后的数据能准确对应原始数据的零点;
3.2.1 INT4 调零
如果我们要称的不是体重,而是温度(原始数据范围 [-20℃ ~ 30℃]),量化后整数范围还是 0~15。
但这里有个问题:原始数据的-20℃要对应量化整数的0,那原始数据的0℃对应量化整数的多少呢?
这个zero_point=6的意思是:原始数据的 0℃,对应量化整数的 6。
结合 scale 和 zero_point,把25℃ 换算成 INT4 刻度:
3.2.2 INT8 调零
我们将温度(原始数据范围 [-20℃ ~ 30℃]),量化后整数范围还是 0~255。
这个zero_point=102意思是:原始数据的 0℃,对应量化整数的 102
结合 scale 和 zero_point,把25℃ 换算成 INT8 刻度:
比特数是差异的根源,量化技术的核心差异源于比特数这一基本物理限制。比特数直接决定了整数能够表示的范围大小和离散精度,这就像不同精度的尺子:
4.1 INT4(4位整数) 则像一把简易直尺:
4.2 INT8(8位整数) 就像一把精密游标卡尺:
4.3 数值基础的意义
理解INT4和INT8的数值基础,就是理解精度与效率取舍的核心矛盾:
这就像选择交通工具:
离散值数量是精度的本质差异,离散值数量决定了量化的"粒度",这是理解精度损失的关键;
离散值对比分析:
视觉化理解:
直观可视化表示:

核心要点:
选择哪种量化方案,核心取决于硬件条件和任务精度要求,以下是具体的决策逻辑:
1. 优先选 INT8 量化的场景
2. 优先选 INT4 量化的场景
3. 折中方案:混合精度量化
如果既想追求 INT4 的速度,又想保留 INT8 的精度,可以采用混合精度量化:
4. 选型决策树

通过一个开源小模型TinyLlama/TinyLlama-1.1B-Chat-v1.0进行INT4量化和 INT8量化的完整代码示例,基于 Hugging Face Transformers + BitsAndBytes 框架实现,包含模型加载、推理测试、显存占用计算,需要在GPU环境下运行。
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig
)
# 选择开源小模型(适合本地测试,可替换为Llama-2、Qwen等大模型)
MODEL_NAME = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
# 测试提示词
PROMPT = "请简要介绍大模型INT4和INT8量化的核心区别"
# 计算模型显存占用的工具函数
def calculate_model_memory_usage(model):
"""计算模型占用的显存大小(单位:MB)"""
total_bytes = 0
for param in model.parameters():
total_bytes += param.nelement() * param.element_size()
for buffer in model.buffers():
total_bytes += buffer.nelement() * buffer.element_size()
return total_bytes / (1024 ** 2)执行以下代码,检查 CUDA 是否可用(GPU 量化必须依赖 CUDA):
import torch
print(torch.cuda.is_available())INT8 量化的优势是生态成熟、精度稳定,无需额外优化策略即可达到理想效果,按以下配置直接运行即可;
# 1. 配置INT8量化参数
int8_quant_config = BitsAndBytesConfig(
load_in_8bit=True, # 启用INT8量化
bnb_8bit_compute_dtype=torch.float16, # 计算时使用float16提升速度
bnb_8bit_use_double_quant=False, # 关闭双重量化(INT8一般不需要)
device_map="auto" # 自动分配模型到GPU/CPU
)
# 2. 加载量化模型和Tokenizer
tokenizer_int8 = AutoTokenizer.from_pretrained(MODEL_NAME)
model_int8 = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=int8_quant_config,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
)
# 3. 测试推理
inputs_int8 = tokenizer_int8(PROMPT, return_tensors="pt").to("cuda")
outputs_int8 = model_int8.generate(
**inputs_int8,
max_new_tokens=150,
temperature=0.7,
do_sample=True
)
# 4. 输出结果和显存占用
print("===== INT8 量化模型输出 =====")
print(tokenizer_int8.decode(outputs_int8[0], skip_special_tokens=True))
print(f"\nINT8 模型显存占用: {calculate_model_memory_usage(model_int8):.2f} MB")INT4 量化必须搭配分组校准和双重量化策略,否则精度损失会很大。
# 1. 配置INT4量化参数(核心优化策略)
int4_quant_config = BitsAndBytesConfig(
load_in_4bit=True, # 启用INT4量化
bnb_4bit_quant_type="nf4", # 归一化浮点量化,适配大模型权重分布
bnb_4bit_compute_dtype=torch.float16, # 计算时使用float16
bnb_4bit_use_double_quant=True, # 启用双重量化,进一步降低误差
bnb_4bit_group_size=128, # 分组校准粒度,128是最优经验值
device_map="auto" # 自动分配设备
)
# 2. 加载量化模型和Tokenizer
tokenizer_int4 = AutoTokenizer.from_pretrained(MODEL_NAME)
model_int4 = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=int4_quant_config,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
)
# 3. 测试推理
inputs_int4 = tokenizer_int4(PROMPT, return_tensors="pt").to("cuda")
outputs_int4 = model_int4.generate(
**inputs_int4,
max_new_tokens=150,
temperature=0.7,
do_sample=True
)
# 4. 输出结果和显存占用
print("\n===== INT4 量化模型输出 =====")
print(tokenizer_int4.decode(outputs_int4[0], skip_special_tokens=True))
print(f"\nINT4 模型显存占用: {calculate_model_memory_usage(model_int4):.2f} MB")===== INT4 量化模型输出 ===== INT4 模型显存占用: 550 MB ===== INT8 量化模型输出 ===== INT8 模型显存占用: 1100 MB
示例总结:

简单而言,大模型INT8和INT4量化,本质就是给笨重的高精度模型减减肥,让它又小又快,还能在普通设备上跑。INT8相当于普通便携秤,有256个刻度(范围 -128~127),减肥后还能保持高精准,误差不到0.5%,一般感觉不出来;INT4 就是超迷你口袋秤,只剩16个刻度(范围 - 8~7),最轻便但误差大,得靠特殊校准才能用得顺手。
量化的核心就是两个关键参数:缩放因子(scale)和零点(zero_point)。scale 像刻度换算比例,把模型原来的大数值范围,等比例压缩到量化后的小整数范围;zero_point 就是给秤调零,确保原始数据的0能对应到量化刻度上,避免整体不准。实际用的时候,选 INT8 还是 INT4 很明确:想省心、要精度,比如企业做智能客服,就选 INT8,中端显卡就能跑,开箱即用;硬件实在受限,比如想在笔记本或在一般设备上部署,就选 INT4,虽然要多花点功夫校准,但能极致省显存、提速度。
总的来说,量化不是瞎压缩,是用一点点精度损失,换存储、显存减半甚至减八成,推理速度还能快 2~5 倍,让原本只能在高端GPU上跑的大模型,在普通环境也能轻松用起来,是大模型落地的关键技巧。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。