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

本文首发于 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 AutoGPTQForCausalLMos.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, tokenizerdef 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() - stprint('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.mzph.cn/news/641933.shtml

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

相关文章

MP4是什么文件格式?如何转换视频格式为MP4?

MP4文件格式&#xff0c;全称MPEG-4 Part 14&#xff0c;源自MPEG&#xff08;Moving Picture Experts Group&#xff09;对数字媒体压缩标准的不断迭代。其产生背景主要是为了适应数字娱乐时代对更高质量、更高效压缩的需求。MP4文件格式在视频、音频和字幕等多媒体元素的集成…

ps发现一张图片上我有些文字我希望扣出去

问: 上面这是在同一个图层中的,一张图片,但是我希望删除: 剩余__次抽奖这几个文字,怎么办? 回答: 选择 快速选择工具, 讲这几个字括起来, 右键选择删除后填充选区, 就实现了将这几个文字删除,

如何在一个集合对象中A排除另外一个集合对象B中A中拥有的数据通用思路,很精妙!

标题是什么意思呢&#xff1f; 假如我有一个集合对象A&#xff0c;数据有1,2,3,4,5,6 另外一个集合对象B&#xff0c;数据有2,4,5 那么在A中排除B拥有的数据就是 最终需要返回的结果就是1,3 那么我们一般一开始的想法其实就是在集合对象中A遍历取到每一个元素&#xff0c;然…

麒麟linux混血安装kali linux工具集合

因为日常要使用麒麟Linux办公&#xff0c;缺少常见的网络管理软件&#xff0c;尝试麒麟linux混血安装kali linux工具集合。 步骤1&#xff1a; 添加Kali的APT源&#xff1a; echo "deb http://http.kali.org/kali kali-rolling main non-free contrib" | sudo tee…

【吃灰开发板复活】DIY全志V3s随身终端屏幕适配,LVGL以及各种外设驱动移植教程

在上周的文章中介绍了一款因作者想要学习Linux而动手DIY的终端设备V3S-PI&#xff0c; 《梦回2004&#xff01;我用全志V3s做了个成本100元&#xff0c;功能媲美MP4的随身终端》&#xff1a;梦回2004&#xff01;我用全志V3s做了个成本100元&#xff0c;功能媲美MP4的随身终端…

[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

数据库缓存策略

数据库缓存策略 以下是数据库与缓存的五种常见策略。 1缓存旁路 缓存旁路&#xff08;Cache-Aside&#xff09; 在缓存旁路策略中&#xff0c;数据库缓存位于数据库旁边。当应用程序请求数据时&#xff0c;它会首先检查缓存 如果缓存中存在数据&#xff08;缓存命中&#xff…

c++:string相关的oj题(415. 字符串相加、125. 验证回文串、541. 反转字符串 II、557. 反转字符串中的单词 III)

文章目录 1. 415. 字符串相加题目详情代码1思路1代码2思路2 2. 125. 验证回文串题目详情代码1&#xff08;按照要求修改后放到新string里&#xff09;思路1代码2(利用双指针/索引)思路2 3. 541. 反转字符串 II题目详情代码1思路1 4. 557. 反转字符串中的单词 III题目详情代码1&…

逆矩阵举例

考虑一个 22的矩阵A 和其逆矩阵A −1的情况&#xff1a; 要求A的逆矩阵&#xff0c;首先计算A的行列式∣A∣&#xff1a; 如果 ∣A∣≠0, 则 A 可逆&#xff0c;逆矩阵 A −1的计算如下&#xff1a; 举例&#xff0c;考虑矩阵&#xff1a; 计算行列式 ∣A∣(24)−(31)8−35…

精品基于Uniapp+springboot智慧校园管理系统App课程选课成绩

《[含文档PPT源码等]精品基于Uniappspringboot智慧校园管理系统App》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;Java 后台框架&#xff1a;springboot、ssm …

leaflet学习笔记-带过滤的图例(九)

前言 图例不只能够帮助我们在查看地图的时候更加方便容易地分辨不同颜色代表的要素&#xff0c;本文要介绍的图例组件还可以按需求过滤掉不用显示的要素&#xff0c;使地图的更能清晰的显示我们需要显示的内容 技术核心 说到过滤要素&#xff0c;第一时间想到的就是滑块组件…

一个大的rosbag数据包怎么分割成一个小的数据包?

文章目录 1. 按时间范围分割&#xff1a;2. 按照消息类型分割&#xff1a;3. 使用split命令&#xff1a;4. 使用Python脚本&#xff1a; 在ROS&#xff08;机器人操作系统&#xff09;中&#xff0c; rosbag是一个用于记录和回放ROS主题消息的工具。如果你有一个大的 rosbag数…

[C++] external “C“的作用和使用场景(案例)

C中extern "C"的作用是什么&#xff1f; 在 C 中&#xff0c;extern "C" 的作用是告诉编译器按照 C 语言的规范来处理函数名和变量名。这是因为 C 编译器会对函数名和变量名进行名称修饰(name mangling)&#xff0c;以区分不同的函数和变量。而在 C 语言中…

搭建互联网医疗平台:构建智慧医院APP的开发指南

本文将从技术层面出发&#xff0c;为大家提供构建互联网医疗平台、打造智慧医院APP的详细开发指南。 一、确定需求与功能 在开始开发之前&#xff0c;首先需要明确智慧医院APP的需求与功能。这包括患者预约挂号、在线咨询、病历查看、医疗报告查询等功能。 二、选择合适的开发…

安科瑞ARTM系列-无线测温解决方案

产品简介 温度在线监测主要是针对高低压开关柜内母排搭接点&#xff0c;断路器触头、电缆接头等电气连接点的温度进行监测&#xff0c;防止在运行过程中因氧化、松动、灰尘等因素造成接点接触电阻过大而发热成为隐患&#xff0c;温度在线监测能够提升设备安全保障&#xff0c;及…

宝塔面板优惠券(折扣券)领取入口及使用教程

宝塔面板是一款服务器管理软件&#xff0c;支持Linux与Windows系统&#xff0c;提供了丰富的功能和插件&#xff0c;让服务器管理变得更加简单、安全、高效。为了让更多用户体验到宝塔面板的便利&#xff0c;官方会不定期推出优惠券活动。本文将为大家详细介绍宝塔面板优惠券的…

ROS:rosdep与ROS2的安装记录

鱼香ROS一键安装&#xff1a; 一键安装微信使用指南 | 鱼香ROS rosdep安装&#xff1a; rosdep 是一个在ROS&#xff08;Robot Operating System&#xff09;生态系统中非常重要的工具&#xff0c;它用于安装ROS包的依赖项。rosdep 确保了ROS包所需的系统依赖项能够被正确安装…

MNIST 数据集详析:使用残差网络RESNET识别手写数字(文末送书)

MNIST 数据集已经是一个几乎每个初学者都会接触的数据集, 很多实验、很多模型都会以MNIST 数据集作为训练对象, 不过有些人可能对它还不是很了解, 那么今天我们一起来学习一下MNIST 数据集&#xff0c;同时构建残差网络来识别手写数字。 1.MNIST 介绍 MNIST手写数字数据库具有…

spring-framework6.x版本源码构建

6.x.修改gradle仓库构建 IDEA版本及gradle构建设置 在gradle指定仓库地址/wrapper/dists/找到与gradle wrapper相对应的gradle版本&#xff0c;在gradle的init.d/目录下新建init.gradle文件&#xff0c;内容如下&#xff1a; allprojects{repositories {mavenLocal()maven { …