LinearQuant是对torch_npu.npu_quant_matmul接口的封装类,完成A8W8、A4W4量化算子的矩阵乘计算。
torch_npu.contrib.module.LinearQuant(in_features, out_features, *, bias=True, offset=False, pertoken_scale=False, output_dtype=None)
x1(计算输入):Device侧的Tensor类型。数据格式支持ND,shape最少是2维,最多是6维。
一个Tensor类型的输出,代表量化matmul的计算结果:
当x1、weight的数据类型均为INT32,每个INT32类型的数据存放8个INT4数据。输入shape需要将数据原本INT4类型时的最后一维shape缩小8倍。INT4数据的最后一维shape应为8的倍数,例如:进行(m, k)乘(k, n)的INT4类型矩阵乘计算时,需要输入INT32类型,shape为(m, k//8)、(k, n//8)的数据,其中k与n都应是8的倍数。x1只能接受shape为(m, k//8)且数据排布连续的数据,weight只能接受shape为(n, k//8)且数据排布连续的数据。
数据排布连续是指数组中所有相邻的数,包括换行时内存地址连续,使用Tensor.is_contiguous返回值为true则表明tensor数据排布连续。
x1(入参) |
weight(变量) |
scale(变量) |
offset(变量) |
bias(变量) |
pertoken_scale(变量) |
output_dtype(入参或变量) |
---|---|---|---|---|---|---|
int8 |
int8 |
int64/float32 |
None |
int32/None |
None |
float16 |
int8 |
int8 |
int64/float32 |
float32/None |
int32/None |
None |
int8 |
注:None表示传入参数或变量为False的场景。 |
x1(入参) |
weight(变量) |
scale(变量) |
offset(变量) |
bias(变量) |
pertoken_scale(变量) |
output_dtype(入参或变量) |
---|---|---|---|---|---|---|
int8 |
int8 |
int64/float32 |
None |
int32/None |
None |
float16 |
int8 |
int8 |
int64/float32 |
float32/None |
int32/None |
None |
int8 |
int8 |
int8 |
float32/bfloat16 |
None |
int32/bfloat16/float32/None |
float32/None |
bfloat16 |
int8 |
int8 |
float32 |
None |
int32/float16/float32/None |
float32/None |
float16 |
int32 |
int32 |
int64/float32 |
None |
int32/None |
None |
float16 |
注:None表示传入参数或变量为False的场景。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import torch import torch_npu import logging import os from torch_npu.contrib.module import LinearQuant x1 = torch.randint(-1, 1, (1, 512), dtype=torch.int8).npu() x2 = torch.randint(-1, 1, (128, 512), dtype=torch.int8).npu() scale = torch.randn(1, dtype=torch.float32).npu() offset = torch.randn(128, dtype=torch.float32).npu() bias = torch.randint(-1,1, (128,), dtype=torch.int32).npu() in_features = 512 out_features = 128 output_dtype = torch.int8 model = LinearQuant(in_features, out_features, bias=True, offset=True, output_dtype=output_dtype) model = model.npu() model.weight.data = x2 model.scale.data = scale model.offset.data = offset model.bias.data = bias # 接口内部调用npu_trans_quant_param功能 output = model(x1) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import torch import torch_npu import logging import os from torch_npu.contrib.module import LinearQuant # 用int32类型承载int4数据,实际int4 shape为x1:(1, 512) x2: (128, 512) x1 = torch.randint(-1, 1, (1, 64), dtype=torch.int32).npu() x2 = torch.randint(-1, 1, (128, 64), dtype=torch.int32).npu() scale = torch.randn(1, dtype=torch.float32).npu() bias = torch.randint(-1,1, (128,), dtype=torch.int32).npu() in_features = 512 out_features = 128 output_dtype = torch.float16 model = LinearQuant(in_features, out_features, bias=True, offset=False, output_dtype=output_dtype) model = model.npu() model.weight.data = x2 model.scale.data = scale model.bias.data = bias output = model(x1) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import torch import torch_npu import torchair as tng from torchair.ge_concrete_graph import ge_apis as ge from torchair.configs.compiler_config import CompilerConfig from torch_npu.contrib.module import LinearQuant import logging from torchair.core.utils import logger logger.setLevel(logging.DEBUG) import os import numpy as np os.environ["ENABLE_ACLNN"] = "true" config = CompilerConfig() npu_backend = tng.get_npu_backend(compiler_config=config) x1 = torch.randint(-1, 1, (1, 512), dtype=torch.int8).npu() x2 = torch.randint(-1, 1, (128, 512), dtype=torch.int8).npu() scale = torch.randn(1, dtype=torch.float32).npu() offset = torch.randn(128, dtype=torch.float32).npu() bias = torch.randint(-1,1, (128,), dtype=torch.int32).npu() in_features = 512 out_features = 128 output_dtype = torch.int8 model = LinearQuant(in_features, out_features, bias=True, offset=True, output_dtype=output_dtype) model = model.npu() model.weight.data = x2 model.scale.data = scale model.offset.data = offset if output_dtype != torch.bfloat16: # 使能高带宽x2的数据排布功能 tng.experimental.inference.use_internal_format_weight(model) model.bias.data = bias model = torch.compile(model, backend=npu_backend, dynamic=False) output = model(x1) |