跳到内容

应用 2:4 稀疏性并可选 FP8 量化

此脚本演示了如何使用 llm-compressor 库,对 Meta-Llama-3-8B-Instruct 模型应用2:4 结构化稀疏性(可选 FP8 量化)。压缩后的模型针对内存效率和支持 GPU 的推理速度进行了优化。

注意: FP8 动态精度计算支持 CUDA 计算能力 9.0 及以上的 Nvidia GPU。

安装

要开始,请安装 llm-compressor 库及其依赖项。

git clone https://github.com/vllm-project/llm-compressor.git
cd llm-compressor
pip install -e .

快速入门

使用以下命令运行脚本:

  • 不带 FP8 量化
python3 llama3_8b_2of4.py
  • 带 FP8 量化
python3 llama3_8b_2of4.py --fp8

该脚本使用以下方法压缩 Meta-Llama-3-8B-Instruct 模型:

  • 2:4 结构化稀疏性: 应用结构化剪枝,将权重减少 50%。
  • FP8 量化(可选): 启用动态量化以进一步节省内存。

配置

  • 模型:meta-llama/Meta-Llama-3-8B-Instruct
  • 数据集:HuggingFaceH4/ultrachat_200k(训练集)
  • 校准样本:512
  • 最大序列长度:2048

运行步骤

  1. 选择模型、数据集和策略

模型和数据集已在脚本中预定义。策略会根据是否启用了 FP8 量化(--fp8 标志)动态调整。

示例策略

recipe = [
    SparseGPTModifier(
        sparsity=0.5,
        mask_structure="2:4",
        targets=[r"re:model.layers.\d*$"],
    )
]

if fp8_enabled:
    recipe.append(
        QuantizationModifier(
            targets=["Linear"],
            ignore=["lm_head"],
            scheme="FP8_DYNAMIC",
        ),
    )
  1. 应用压缩 脚本使用 oneshot 函数应用压缩。
oneshot(
    model=model,
    dataset=ds,
    recipe=recipe,
    max_seq_length=2048,
    num_calibration_samples=512,
)

保存压缩后的模型

压缩后的模型和 tokenizer 将被保存到输出目录。

model.save_pretrained(save_dir, save_compressed=True)
tokenizer.save_pretrained(save_dir)

输出目录:- 无 FP8:Meta-Llama-3-8B-Instruct-2of4-sparse - 带 FP8:Meta-Llama-3-8B-Instruct-2of4-W8A8-FP8-Dynamic-Per-Token

不进行稀疏压缩的保存

要将模型保存到磁盘而不进行稀疏压缩:

model.save_pretrained(save_dir, save_compressed=True, disable_sparse_compression=True)
tokenizer.save_pretrained(save_dir)

注意: 同时使用 save_compresseddisable_sparse_compression 选项保存模型时,将使用量化压缩器压缩模型;但是,为了节省磁盘空间,将使用密集稀疏压缩器,而不是更节省磁盘空间的稀疏压缩器。dense 稀疏压缩器按原样保存模型参数,不利用稀疏性来节省磁盘空间。这些选项仅影响模型在磁盘上的保存方式,而不影响实际的剪枝或量化过程。

验证

压缩后,脚本将通过生成示例输出来验证模型。

========== SAMPLE GENERATION ============
Hello my name is ...
=========================================

注意: - 确保您的 GPU 有足够的内存(至少约 25GB)来运行压缩脚本。 - 使用 --fp8 标志来启用 FP8 量化。

修改 MODEL_IDDATASET_ID 变量以使用其他模型或数据集。

在 vLLM 中运行

使用 pip install vllm 安装 vLLM。

# run_model.py

import argparse
from vllm import LLM, SamplingParams

def run_inference(model_path, tensor_parallel_size, prompt="Hello my name is:"):
    """
    Loads a model and performs inference using LLM.
    """
    # Define sampling parameters
    sampling_params = SamplingParams(
        temperature=0.8,
        top_p=0.95,
    )
    # Load the model
    model = LLM(
        model=model_path, 
        enforce_eager=True,
        dtype="auto",
        tensor_parallel_size=tensor_parallel_size,
    )

    # Generate inference
    outputs = model.generate(prompt, sampling_params=sampling_params)
    return outputs[0].outputs[0].text

def main():
    """ Main function to handle CLI and process the model. """
    # Argument parsing
    parser = argparse.ArgumentParser(description="Run inference on a single model and print results.")
    parser.add_argument(
        "model_path",
        type=str,
        help="Path to the model to perform inference."
    )
    parser.add_argument(
        "--tensor_parallel_size",
        type=int,
        default=1,
        help="Tensor parallel size for the model. Default is 1."
    )

    args = parser.parse_args()
    model_path = args.model_path
    tensor_parallel_size = args.tensor_parallel_size

    prompt = "Hello my name is:"

    # Load model and perform inference
    inference_result = run_inference(model_path, tensor_parallel_size)
    print("="* 20)
    print("Model:", model_path)
    print(prompt, inference_result)

if __name__ == "__main__":
    main()

运行模型的命令

python3 run_model.py <MODEL_PATH>

示例

python3 run_model.py Meta-Llama-3-8B-Instruct2of4-W8A8-FP8-Dynamic-Per-Token