使用NVIDIA TensorRT-LLM支持CodeFuse-CodeLlama-34B上的int4量化和推理优化实践

news2024/11/6 3:02:17

本文首发于 NVIDIA

一、概述

CodeFuse(https://github.com/codefuse-ai)是由蚂蚁集团开发的代码语言大模型,旨在支持整个软件开发生命周期,涵盖设计、需求、编码、测试、部署、运维等关键阶段。
 

为了在下游任务上获得更好的精度,CodeFuse 提出了多任务微调框架(MFTCoder),能够解决数据不平衡和不同收敛速度的问题。
 

通过对比多个预训练基座模型的精度表现,我们发现利用 MFTCoder [1,2] 微调后的模型显著优于原始基座模型。其中,尤为值得关注的是采用了 MFTCoder 框架,并利用多任务数据集进行微调的 CodeFuse-CodeLlama-34B [3] 模型,在 HumanEval 评估数据集中取得了当时的最好结果。具体来说,基于 CodeLlama-34b-Python 模型进行微调的 CodeFuse-CodeLlama-34B 在 HumanEval-python 上实现了 74.4% 的 pass@1(贪婪解码)。以下是完整的代码能力评估结果 :

在代码补全、text2code、代码翻译、单测生成以及代码生成任务上,CodeFuse-CodeLlama-34B 全面超过 GPT-3.5;CodeFuse-CodeLlama-34B 能够在单测生成和代码补全(HumanEval )任务上超过 GPT-4。同时,上述微调模型、MFTCoder 训练框架和高质量代码数据集已经开源(github: https://github.com/codefuse-ai)。
 

然而,CodeFuse-CodeLlama-34B 的部署遇到了如下两个挑战:
 

1)数据类型为 fp16 的 34B 模型,显存占用为 68 GB,至少需要 3 张 A10 才能加载模型,部署成本很高;

2)在模型推理的生成阶段,通常伴随着长条形的矩阵运算,此时计算量较小,不足以掩盖 GPU 的访存延迟,即 memory bound 问题,此时程序的性能受限于 GPU 带宽。

为了解决上述问题,我们利用 GPTQ 量化技术,在降低了部署成本的同时,也缓解了 GPU 的带宽压力 ,从而显著提升了推理速度。最终,CodeFuse-CodeLlama-34B 的 int4 量化模型可以部署在单张 A10 显卡上,推理速度可以达到 20 tokens/s (batch_size=1)。同时,相较于 fp16 数据精度的模型,通过算法上的优化,int4 量化引入的精度下降可以控制在 1% 以内。下面,我们从模型量化和测试两个方面展示我们是如何实现 CodeFuse-CodeLlama-34B 模型的 int4 量化部署的。另外,TensorRT-LLM 也支持了 CodeFuse 中基于 MFTCoder 训练的开源模型部署。
 

二、CodeFuse-CodeLlama-34B int4 量化


这里我们使用 GPTQ [4] 技术对模型进行 int4 量化。GPTQ 是对逐层量化范式经典框架 OBQ(Optimal Brain Quantization)[5] 的高效实现,能够利用单张 A100-80G 在 4 小时内完成 OPT-175B 模型的量化,并且可以获得较好的准确率。
 

另外,我们这里采用了静态量化方式,即通过矫正数据离线地进行量化,得到诸如缩放因子和零点的量化参数,在推理时不再进行量化参数的更新。与之对应的是动态量化,会在模型推理的同时根据输入进行量化参数的调整。最后,我们这里进行的是 int4-weight-only 量化,即只对权重进行量化而不对层输入进行量化,即 W4A16 量化。
 

GPTQ 算法


 

  1. 所有输出通道共享相同的量化顺序,从而使得行间共享同一份 Hessian 矩阵,大大减少了算法计算量。
  2. 使用一次 Cholesky 分解代替了在 GPTQ 每次迭代中对整个 Hessian 矩阵的逆矩阵的高斯消元迭代更新方式。既大大减少了计算量,又得以利用成熟 GPU 矩阵库中的 Cholesky 算法,且避免了迭代更新方式在矩阵运算中所带来的数值不稳定问题。
  3. 通过将整个计算过程由对单个输入通道进行更新,等效转变为划分 batch 并逐 batch 更新的方式,避免了每次量化对整个 Hessian 与权重矩阵的 GPU 读写操作,大大降低了 GPU 访存数量。
     

上述的改进使得 GPTQ 可以有效提升 GPU 利用率,从而能够对大模型进行高效量化。

三、int4-weight-only 量化

这里我们利用开源工具 AutoGPTQ(https://github.com/PanQiWei/AutoGPTQ)进行量化,工具超参数如下;


 

利用 AutoGPTQ 进行模型加载和推理的例子如下:
 

import os
import torch
import time
from modelscope import AutoTokenizer, snapshot_download
from auto_gptq import AutoGPTQForCausalLM

os.environ["TOKENIZERS_PARALLELISM"] = "false"

def load_model_tokenizer(model_path):
    """
    Load model and tokenizer based on the given model name or local path of downloaded model.
    """
    tokenizer = AutoTokenizer.from_pretrained(model_path, 
                                              trust_remote_code=True, 
                                              use_fast=False,
                                              lagecy=False)
    tokenizer.padding_side = "left"
    tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids("<unk>")
    tokenizer.eos_token_id = tokenizer.convert_tokens_to_ids("</s>")

    model = AutoGPTQForCausalLM.from_quantized(model_path, 
                                                inject_fused_attention=False,
                                                inject_fused_mlp=False,
                                                use_cuda_fp16=True,
                                                disable_exllama=False,
                                                device_map='auto'   # Support multi-gpus
                                              )
    return model, tokenizer


def inference(model, tokenizer, prompt):
    """
    Uset the given model and tokenizer to generate an answer for the speicifed prompt.
    """
    st = time.time()
    inputs = prompt if prompt.endswith('\n') else f'{prompt}\n'

    input_ids = tokenizer.encode(inputs, 
                                  return_tensors="pt", 
                                  padding=True, 
                                  add_special_tokens=False).to("cuda")
    with torch.no_grad():
        generated_ids = model.generate(
            input_ids=input_ids,
            top_p=0.95,
            temperature=0.1,
            do_sample=True,
            max_new_tokens=512,
            eos_token_id=tokenizer.eos_token_id,
            pad_token_id=tokenizer.pad_token_id              
        )
    print(f'generated tokens num is {len(generated_ids[0][input_ids.size(1):])}')
    outputs = tokenizer.batch_decode(generated_ids, skip_special_tokens=True) 
    print(f'generate text is {outputs[0][len(inputs): ]}')
    latency = time.time() - st
    print('latency is {} seconds'.format(latency))

    
if __name__ == "__main__":
    model_dir = snapshot_download('codefuse-ai/CodeFuse-CodeLlama-34B-4bits', revision='v1.0.0')

    prompt = 'Please write a QuickSort program in Python'

    model, tokenizer = load_model_tokenizer(model_dir)
    inference(model, tokenizer, prompt)

在做静态量化时,GPTQ 使用矫正数据集作为输入计算 Hessian 矩阵,从而更新未量化权重进而补偿量化带来的误差。如果推理阶段的输入和矫正数据集有偏差(bias),那么量化时用矫正数据得到的 Hessian 矩阵就无法完全反映推理输入,这会导致 GPTQ 的误差补偿失效(失效的程度和偏差成正比),出现量化模型在推理输入上量化误差变大的情况,进而导致量化模型的精度下降。
 

为了解决上述问题,对于微调模型,我们使用了一种数据分布对齐技术减少模型量化带来的损失。通过抽取训练数据(CodeFuse 开源的高质量代码数据集 evol)中的 Question 作为引导方式,利用原始模型生成 Answer,将 Question 和 Answer 拼接起来作为矫正数据;最终在 HumanEval Benchmarks 的 Python pass@1 取得了 73.8% 的准确率,相较于 bf16 模型仅有 0.6% 的精度损失。同时,在 CMNLI 和 C-Eval 两个数据集的精度损失也比较少。

四、构建 TensorRT 引擎

在通过 AutoGPTQ 可以得到 safetensors 格式的 int4 量化模型 [6] 后,我们的目标是构建单卡 TensorRT 引擎,同时保证 activation 是 fp16 的数据精度。通过 examples/llama/build.py 进行 TensorRT 引擎构建时,需要关注如下参数:
 

  • dtype:设置为 fp16
  • use_gpt_attention_plugin:设置为 fp16,构建引擎时利用 gpt a ttention plugin 并且数据精度为 fp16
  • use_gemm_plugin:设置为 fp16,构建引擎时利用 gemm_plugin 并且数据精度为 fp16
  • use_weight_only:触发 weight only 量化
  • weight_only_precision:设置为 int4 _gptq,表示构建 W4A16 的 GPTQ 量化模型引擎
  • per_group:gptq 为group-wise 量化,所以需要触发 per-group
  • max_batch_size: TensorRT 引擎最大允许 batch size
  • max_input_len:TensorRT 引擎最大允许输入长度
  • max_output_len:TensorRT 引擎最大允许输出长度 
     

综上,我们在单卡 A10/A100 上构建 TensorRT 引擎的命令如下:

python build.py --model_dir  "${model_dir}" \
                --quant_safetensors_path "${quant_safetensors_path}" \
                --dtype float16 \
                --use_gpt_attention_plugin float16 \
                --use_gemm_plugin float16 \
                --use_weight_only \
                --weight_only_precision int4_gptq \
                --max_batch_size 1 \
                --max_input_len 2048 \
                --max_output_len 1024 \
                --per_group \
                --output_dir "${engin_dir}" 2>&1  | tee dev_build.log

五、测试
 

性能

下面,我们主要测试了 batch size 为 1 时,不同的输入输出长度和量化精度情况下,TensorRT-LLM 在 A10/A100 上的推理速度表现。可以看到,在 A100 上,TensorRT-LLM 的 int4 相对 fp16,最高能够带来 2.4 倍的加速,相对 int8 最高也能带来 1.7 倍的加速。
 

注意:以上性能测试均基于 TensorRT-LLM 的 0.6.1 版本

显存占用和结果测试

我们测量了模型加载后占用的显存占用情况,以及输入 2048/1024 tokens 并输出 1024/2048 tokens 时的显存使用情况;同时我们也测试了量化前后的精度情况,如下表所示:

可见,4bit 量化后,显存占用大幅缩小,在一张 A10(24GB 显存)上就能部署 34B 的大模型,具备非常好的实用性。

六、模型演示

我们通过终端命令行 [7] 以及网页聊天机器人 [8] 两种不同的方式,展示我们最终的推理效果,具体细节可以访问开源的链接。 
 

Cli Demo
 


 

Webui Demo


​​​​​​​

七、总结
 

在这篇文章中,我们介绍了如何使用 TensorRT-LLM 来加速 CodeFuse 的推理性能。具体而言,我们按照顺序展示了如何使用 GPTQ Int4 量化方法、增强 GPTQ 量化算法精度的自动对齐技术、TensorRT-LLM int4 量化模型的使用方法以及相应的评估过程。通过 TensorRT-LLM 的支持,CodeFuse 实现了较低的推理延迟和优化的部署成本。欢迎大家关注 CodeFuse 获取最新发布的更高准确率的微调大模型。 
 

参考资料:

[1] Liu, B., Chen, C., Liao, C., Gong, Z., Wang, H., Lei, Z., Liang, M., Chen, D., Shen, M., Zhou, H., Yu, H., & Li, J. (2023). MFTCoder: Boosting Code LLMs with Multitask Fine-Tuning. ArXiv, abs/2311.02303.

[2] Zhang, Z., Chen, C., Liu, B., Liao, C., Gong, Z., Yu, H., Li, J., & Wang, R. (2023). Unifying the Perspectives of NLP and Software Engineering: A Survey on Language Models for Code.

[3] https://huggingface.co/codefuse-ai/CodeFuse-CodeLlama-34B

[4] Frantar, E., Ashkboos, S., Hoefler, T., & Alistarh, D. (2022). GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers. ArXiv, abs/2210.17323.

[5] Frantar, E., Singh, S. P., Alistarh, D. (2022). Optimal Brain Compression: A Framework for Accurate Post-Training Quantization and Pruning. Advances in Neural Information Processing Systems, 35, 4475-4488.

[6] https://huggingface.co/codefuse-ai/CodeFuse-CodeLlama-34B-4bits

[7] Codefuse-ai: https://github.com/codefuse-ai

[8] Codefuse-chatbot: https://github.com/codefuse-ai/codefuse-chatbot

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1413271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【idea打包】idea打包项目了,虽然出现BUILD SUCCESS,但是jar是个无法启动的jar

idea的打包问题 问题怎么解决解决后的样子运行成功的样子 问题 我执行打包命令后生成一个jar&#xff0c;但是在执行 java -jar 命令之后出现了一下的情况 打开jar包里面的MANIFEST.MF 里面是这样的 Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Built-By: WX…

【华为 ICT HCIA eNSP 习题汇总】——题目集10

1、以下哪个动态路由协议不能应用在 IPv6 网络中&#xff1f; A、IS-IS B、RIPng C、BGP4 D、OSPFv3 考点&#xff1a;路由技术原理 解析&#xff1a;&#xff08;A&#xff09; IS-ISv6 是在 IPv6 环境下&#xff0c;IS-IS 协议进行了相应的扩展和改进&#xff0c;以适应 IPv6…

LC 2846. 边权重均等查询

2846. 边权重均等查询 难度&#xff1a; 困难 题目大意&#xff1a; 现有一棵由 n 个节点组成的无向树&#xff0c;节点按从 0 到 n - 1 编号。给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges &#xff0c;其中 edges[i] [ui, vi, wi] 表示树中存在一条位于节点 …

AI数字人-数字人视频创作数字人直播效果媲美真人

在科技的不断革新下&#xff0c;数字人技术正日益融入到人们的生活中。近年来&#xff0c;随着AI技术的进一步发展&#xff0c;数字人视频创作领域出现了一种新的创新方式——AI数字人。数字人视频通过AI算法生成虚拟主播&#xff0c;其外貌、动作、语音等方面可与真实人类媲美…

element-UI上传文件后valid提示不消失

问题描述&#xff1a;上传文件完成后&#xff0c;必填信息提示不消失 解决方法&#xff1a;在<el-form-item>标签添加show-message属性&#xff0c;字段为空时才显示提示信息 <el-form-item :prop"fileList" :show-message"!form.fileList || !form.f…

命令行启动Android Studio模拟器

1、sdk路径查看&#xff08;打开Android Studio&#xff09; 以上前提是安装的Android Studio并添加了模拟器&#xff01;&#xff01;&#xff01; 2、复制路径在终端进入到 cd /Users/duxi/Library/Android/sdk目录&#xff08;命令行启动不用打开Android Studio就能运行模拟…

C++逆向分析--虚函数(多态的前置)

先理解一件事&#xff0c;在intel汇编层面来说&#xff0c;直接调用和间接调用的区别。 直接调用语法&#xff1a; call 地址 硬编码为 &#xff1a;e8 间接调用语法: call [ ...] 硬编码为: FF 那么在C语法中&#xff0c;实现多态的前提是父类需要实现多态的成员…

跟无神学AI之Prompt

在大模型时代会写prompt变得很重要。 Prompt翻译为中文为提示词&#xff0c;在大模型的特定领域指的是大模型使用者给大模型提交的一种有一定格式的交互命令&#xff0c;让我们看看科大讯飞的大模型给出的答案—— Prompt是一种向人工智能模型提供的输入文本或指令&#xff0…

今日AI大热潮,明日智能风向标

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

YOLO系列(YOLO1-YOLO5)技术规格、应用场景、特点及性能对比分析

文章目录 前言一、YOLOv1-YOLOv5技术规格对比&#xff1a;二、主要应用场景和特点&#xff1a;三、性能对比分析&#xff1a;四、市场应用前景及对不同用户群体的潜在影响&#xff1a;总结 前言 YOLO&#xff08;You Only Look Once&#xff09;系列模型作为一种实时目标检测算…

【数据库学习】pg安装与运维

1&#xff0c;安装与配置 #安装 yum install https:....rpm1&#xff09;安装目录 bin目录&#xff1a;二进制可执行文件目录&#xff0c;此目录下有postgres、psql等可执行程序&#xff1b;pg_ctl工具在此目录&#xff0c;可以通过pg_ctl --help查看具体使用。 conf目录&…

Linux实现:从倒计时到进度条

文章目录 1.回车与换行2.缓冲区的概念3.倒计时4.进度条(第一版无应用场景)5.进度条(第二版有应用场景) 1.回车与换行 2.缓冲区的概念 强制刷新可以使用冲刷函数fflush #include <stdio.h> #include <unistd.h> int main() {printf("I am a \nhandsome man!&q…

HTML - 介绍

一.简介 HTML&#xff0c;超文本标记语言&#xff08;HyperText Markup Language&#xff09;&#xff0c;是一种用于创建网页的标准标记语言。我们可以使用HTML建立自己的WEB网站或特定页面。HTML运行在浏览器上&#xff0c;由浏览器解析。 ⚠️注意&#xff1a;HTML文件的后缀…

STM32连接阿里云物联网平台

文章目录 引言一、STM32连接阿里云物联网平台思路二、ESP8266烧录固件三、使用AT指令连接阿里云物联网平台四、STM32环形串口缓冲区驱动程序五、STM32连接阿里云驱动程序 引言 连续写了两篇关于阿里云连接的文章&#xff0c;都是使用Arduino ESP8266 & Arduino ESP32的方式…

【虚拟机数据恢复】异常断电导致虚拟机无法启动的数据恢复案例

虚拟机数据恢复环境&#xff1a; 某品牌R710服务器MD3200存储&#xff0c;上层是ESXI虚拟机和虚拟机文件&#xff0c;虚拟机中存放有SQL Server数据库。 虚拟机故障&#xff1a; 机房非正常断电导致虚拟机无法启动。服务器管理员检查后发现虚拟机配置文件丢失&#xff0c;所幸…

【论文阅读】GraspNeRF: Multiview-based 6-DoF Grasp Detection

文章目录 GraspNeRF: Multiview-based 6-DoF Grasp Detection for Transparent and Specular Objects Using Generalizable NeRF针对痛点和贡献摘要和结论引言模型框架实验不足之处 GraspNeRF: Multiview-based 6-DoF Grasp Detection for Transparent and Specular Objects Us…

Vulnhub靶场DC-9

攻击机192.168.223.128 靶机192.168.223.138 主机发现 nmap -sP 192.168.223.0/24 端口扫描 nmap -sV -p- -A 192.168.223.138 开启了22 80端口 访问一下web页面 有个查询界面 测试发现存在post型的sql注入 用sqlmap跑一下&#xff0c;因为是post型的&#xff0c;这里…

C#使用RabbitMQ-1_Docker部署并在c#中实现简单模式消息代理

介绍 RabbitMQ是一个开源的消息队列系统&#xff0c;实现了高级消息队列协议&#xff08;AMQP&#xff09;。 &#x1f340;RabbitMQ起源于金融系统&#xff0c;现在广泛应用于各种分布式系统中。它的主要功能是在应用程序之间提供异步消息传递&#xff0c;实现系统间的解耦和…

RabbitMQ问题总结

:::info 使用场景 异步发送&#xff08;验证码、短信、邮件。。。&#xff09;MySQL 和 Redis、ES 之间的数据同步分布式事务削峰填谷… ::: 如何保证消息不丢失 上图是消息正常发送的一个过程&#xff0c;那在哪个环节中消息容易丢失&#xff1f;在哪一个环节都可能丢失 生…

Ubuntu20.4 Mono C# gtk 编程习练笔记(四)

连续实时绘图 图看上去不是很清晰&#xff0c;KAZAM录屏AVI尺寸80MB&#xff0c; 转换成gif后10MB, 按CSDN对GIF要求&#xff0c;把它剪裁缩小压缩成了上面的GIF&#xff0c;图像质量大不如原屏AVI&#xff0c;但应该能说明原意&#xff1a;随机数据随时间绘制在 gtk 的 drawin…