量化、KV缓存与吞吐预算:练习答案
参考实现
独立运行:
python
def kv(b,t):
return 2*b*t*32*8*128*2
assert kv(2,8192) == 4*kv(1,4096)同一推理进程的模型参数通常共享,KV保存每个序列的状态,因此随batch和长度增长;多进程复制模型则另当别论。
离群权重与负侧裁剪
下面是独立答案文件,不依赖正文的全局变量。在相同 torch==2.8.0 CPU 环境保存为 quantization_answer.py 运行。
python
import torch
import torch.nn.functional as F
torch.set_num_threads(1)
W=torch.tensor([[.02,-.03,.04,.05],[2.2,-3.1,4.2,80.]],dtype=torch.float32)
X=torch.tensor([[.5,-.25,.75,1.],[2.,-1.,.5,-.5]],dtype=torch.float32)
bias=torch.tensor([.1,-.2])
y=F.linear(X,W,bias)
scale=W.abs().max().item()/127
q_tensor=torch.quantize_per_tensor(W,scale,0,torch.qint8)
# axis=0 每个输出行独立尺度;不能误用输入列 axis=1。
scales=W.abs().amax(dim=1).double()/127
zero_points=torch.zeros(W.shape[0],dtype=torch.int64)
q_channel=torch.quantize_per_channel(W,scales,zero_points,axis=0,dtype=torch.qint8)
yt=F.linear(X,q_tensor.dequantize(),bias)
yc=F.linear(X,q_channel.dequantize(),bias)
et=(y-yt).abs().amax(dim=0)
ec=(y-yc).abs().amax(dim=0)
assert torch.equal(q_tensor.int_repr()[0],torch.zeros(4,dtype=torch.int8))
assert ec[0]<et[0]
# 第二行含离群值,两种尺度一样;按行量化不能消除行内离群问题。
assert torch.allclose(ec[1],et[1],atol=1e-5)
print('per-output max error; tensor',et.tolist(),'channel',ec.tolist())
print('per-channel scales',scales.tolist())
# 用与正文不同的输入检查欠校准:负端也会饱和,不能只看正最大值。
calibration=torch.tensor([-.5,.25,.5])
new_x=torch.tensor([[-2.,.25,0.,.5]])
s=calibration.abs().max().item()/127
qx=torch.quantize_per_tensor(new_x,s,0,torch.qint8)
rounded=torch.round(new_x/s)
mask=(rounded < -128)|(rounded > 127)
assert mask.sum().item()==1 and qx.int_repr()[0,0].item()==-128
assert qx.dequantize()[0,0].item()>-1.0
output=F.linear(qx.dequantize(),q_channel.dequantize(),bias)
reference=F.linear(new_x,W,bias)
assert not torch.allclose(output,reference,atol=.1)
print('negative out-of-range input clipped; max output error',(output-reference).abs().max().item())全张量尺度约0.62992,第一行四个小权重都量化成0,因此第一输出维度最大误差约0.09750。按行后第一行尺度约0.0003937,误差降到约0.0001575;第二行尺度仍由80决定,两种方式该输出维度误差都约0.46614。按通道可以隔离不同输出行的动态范围,不能自动修复行内离群值。
新输入的-2映射到整数-508,低于qint8下限,实际饱和为-128,反量化约-0.50394;固定输入比较的最大输出误差约3.42908。把校准范围扩大可减少这种裁剪,同时会增大每个格点间隔;增加bit数则增加可用格点数,在相同范围内缩小间隔,但改变存储和硬件支持条件。两者都要在独立代表性样本上重测,不能只挑这一题好看的指标。
返回题目。