2. 简介

TopsCompressor 是一个大模型量化压缩工具包,旨在提供便捷python api帮助模型开发人员进行模型量化压缩等任务。

3. 安装使用说明

TopsCompressor支持Python3.8及以上版本,可以从whl包直接安装。

3.1. 使用预编译的whl包安装

pip3 install topscompressor-<version>-py3-none-any.whl

GPU量化: 依赖于pytorch gpu及对应版本torchvision

GCU量化: 依赖于pytorch cpu及torch-gcu和对应版本torchvision

通过如下命令检查相关依赖是否已经安装:

python3 -m pip list | grep torch-gcu
python3 -m pip list | grep torch
python3 -m pip list | grep torchvision

如果已经正常安装,可以显示如下内容:

torch-gcu                         2.5.1+<version>
torch                             2.5.1+cpu
torchvision                       0.20.1+cpu

如果未安装,可以通过以下方式安装依赖包:

python3 -m pip install torch==2.5.1+cpu -i https://download.pytorch.org/whl/cpu
python3 -m pip install torchvision==0.20.1 -i https://download.pytorch.org/whl/cpu
python3 -m pip install torch_gcu-2.5.1+<version>*.whl

4. 用户使用说明

TopsCompressor可以支持基于Huggingface models的LLM类模型量化和基于onnx格式的传统模型量化两种场景。LLM类模型量化当前提供awq、gptq、w8a16、w8a8和int8 kvcache量化功能。传统模型量化当前支持PTQ量化功能。

4.1. 支持范围

LLM类模型量化

  • 支持Huggingface模型格式。

  • AWQ量化

    • W4A16:只支持group size是64或64整数倍的模型量化。

    • 其余配置暂不支持。

  • GPTQ量化

    • W4A16:只支持group size是64或64整数倍的模型量化。

    • 当前算子实现不支持g_idx是乱序情况,即量化时,desc_act=True, static_groups=False的情况。

  • W8A16量化

    • 当前量化方式:per-channel,group size=-1的int8对称量化。

  • W8A8量化

    • 当前量化方式:权重支持per-channel的int8对称量化,激活支持per-tensor的int8对称量化。

  • Int8 KVCache量化

    • 当前量化支持int8对称和非对称量化,当前量化int8 kv需要在原模型基础上与上述量化分开执行。

传统模型量化

  • 支持onnx模型格式。

  • 支持PTQ量化方式。

    • 校准过程中的数据分布统计,支持kl散度、mixmax、移动平均、百分位数等方式

    • 支持FP32+FP16+INT8混精

4.2. 功能列表

LLM类模型量化

  • AWQ量化

  • GPTQ量化

  • W8A16量化

  • W8A8量化

  • Int8 kvcache量化

  • 自定义数据集

AWQ量化

使用python api量化方式
from topscompressor.quantization.quantize import quantize, save_quantized_model
from topscompressor.quantization.config import QuantConfig

# create awq quant config
quant_config = QuantConfig.create_config("awq")

# create calibration dataset, such as 'wikitext'
calib_data_name = 'wikitext'
calib_data_config = {
    'name': 'wikitext-2-raw-v1',
    'split': 'validation',
}

# quantize model, such as LLaMA2 7b, the model name can be local or online checkpoint (hf format).
model = quantize(
    "Llama-2-7b-hf",
    quant_config,
    calib_data=calib_data_name,
    calib_data_load_fn_kwargs=calib_data_config,
    calib_data_max_len=512,
    n_samples=128,
    device='gcu'
)

# save quantized model
save_quantized_model(model, quant_config, "saved_dir")

GPTQ量化

  • 上述代码只需修改quant_config部分

    # create gptq quant config
    quant_config = QuantConfig.create_config("gptq")

W8A16量化

  • 上述代码只需修改quant_config部分

    # create w8a16 quant config
    quant_config = QuantConfig.create_config("w8a16")

W8A8量化

  • 上述代码只需修改quant_config部分

    # create w8a8 quant config
    quant_config = QuantConfig.create_config("w8a8")

Int8 kvcache量化

from topscompressor.quantization.quantize import quantize, save_kvcache_params, accelerate_gptq_pack_model
from topscompressor.quantization.config import QuantConfig

def main(args):
    accelerate_gptq_pack_model()
    kv_config = QuantConfig.create_config('int8_kv')
    kv_config.sym_quant_kv = False
    kv_config.is_quantized_model = False
    calib_data_name = 'wikitext'
    calib_data_config = {
        'name': 'wikitext-2-raw-v1',
        'split': 'validation',
    }
    model = quantize(
        "Llama-2-7b-hf",
        kv_config,
        calib_data=calib_data_name,
        calib_data_load_fn_kwargs=calib_data_config,
        calib_data_max_len=512,
        n_samples=128,
        device='gcu'
    )

    save_kvcache_params(model, quant_config, "saved_dir")

自定义数据集

对于自定义数据集,当前支持一种简单方式,将文本保存到list中,然后传递给quantize函数。

    calib_data = [
        'sample 1',
        'sample 2',
        ...,
        'sample n'
    ]
    ...
    quantize(
        model,
        quant_config,
        calib_data=calib_data,
        ...
    )

量化后模型

模型量化后以Huggingface models形式组织,将原始模型中其余相关文件(tokenizer等)拷贝到量化模型目录下即可使用。

传统模型量化

PTQ量化

使用python api量化方式
import onnxruntime
from topscompressor.onnx.quantization.quantize import quantize, CalibrationDataReader, QuantFormat, QuantType,CalibrationMethod, QuantizationMode

class InceptionV3DataReader(CalibrationDataReader):
    def __init__(self, calibration_image_folder, size_limit=0,augmented_model_path='augmented_model.onnx'):
        self.image_folder = calibration_image_folder
        self.augmented_model_path = augmented_model_path
        self.sizelimit = size_limit
        self.datasize, self.enum_data_dicts = self._preproc()

    def _preproc(self):
        EP_list = ['CPUExecutionProvider']
        session = onnxruntime.InferenceSession(self.augmented_model_path, None, providers=EP_list)
        (_, _, height, width) = session.get_inputs()[0].shape
        nhwc_data_list = preprocess_func(self.image_folder, height, width, self.sizelimit)
        input_name = session.get_inputs()[0].name
        return len(nhwc_data_list), iter([{input_name: nhwc_data} for nhwc_data in nhwc_data_list])


    def get_next(self):
        return next(self.enum_data_dicts, None)

def preprocess_func(images_folder, height, width, size_limit=0):
    ...

# create calibration DataReader, such as 'imagenet'
# using 1000 image samples to do calibration
dr = InceptionV3DataReader("path_to_imagenet",1000 ,"inception_v3-torchvision-op13-fp32-N.onnx")

# int8 model will be saved as inception_v3_quant.onnx
quantize("inception_v3-torchvision-op13-fp32-N.onnx",
                "inception_v3_quant.onnx",
                dr,
                quant_format=QuantFormat.PTQ,
                per_channel=True,
                nodes_to_exclude=['Gemm_261'],
                activation_type=QuantType.QInt8,
                nodes_to_maxthreshold=[],
                weight_type=QuantType.QInt8,
                calibrate_method=CalibrationMethod.Entropy,
                quantization_mode = QuantizationMode.QuantOps)

量化后模型

模型量化后以onnx形式组织,可用于在燧原推理软件栈(或其他已对接燧原量化op的平台)上推理。