提升ChatGLM效能:仅需简单模型调整

news2024/11/16 13:25:03
本文作者:

赵桢、罗成、李亭骞、邹文艺

引言

自大语言模型 (LLM) 成为热点话题以来,涌现了一大批中文大语言模型并在优化平台中得到了积极部署。ChatGLM 正是广受好评的主流中文大语言模型之一。

然而,由于 ChatGLM 模型尚未成为 Transformer 生态的原生模型,因此,官方 optimum 扩展库对其仍缺乏支持。

本文提供了一种使用 OpenVINO

opset 重构该模型架构的便捷方法。

该方案包含专为 ChatGLM 定制的优化节点,且这些节点都利用英特尔
®
高级矩阵扩展(Intel
®
Advanced Matrix Extensions,缩写为英特尔
®
AMX)内联和 MHA(Multi-Head Attention,多头注意力)融合实现了高度优化。

请注意,本文仅介绍了通过为 ChatGLM 创建 OpenVINO

stateful模型实现优化的解决方案。本方案受平台限制,必须使用内置了英特尔
®
AMX 的第四代英特尔
®
至强
®
可扩展处理器
[1]
(代号 Sapphire Rapids)。笔者不承诺对该解决方案进行任何维护。

ChatGLM 模型简介

笔者在查看 ChatGLM 原始模型的源码
[2]
时,发现 ChatGLM 与 Optimum ModelForCasualML并不兼容,而是定义了新的类 ChatGLMForConditionalGeneration
[3]

该模型的流水线回路包含 3 个主要模块(Embedding、GLMBlock 层
[4]
和 lm_logits),结构如下:

图1 ChatGLM 模型结构

如上图所示,整个流水线实际要求模型有两个不同的执行图,使用输入提示符进行首次推理时不需要 KV 缓存作为 GLMBlock 层的输入。从第二次迭代开始,QKV 注意力机制的上一次结果将成为当前一轮模型推理的输入。

随着生成符的长度不断增加,在流水线推理过程中,模型输入和输出之间将存留大量的大型内存副本。

以 ChatGLM6b 默认模型配置
[5]
为示例,输入和输出阵列之间的内存副本类似于以下伪代码,其内存拷贝的开销由模型的参数 hidden_size 以及迭代的次数决定:

while(eos_token_id || max_seq_len){
    memcpy(model_inp, model_outp, num_layer*2*sizeof(model_outp)* hidden_size)
    model_outp.push_back(gen_token)
}
△代码若显示不全,可左右滑动

因此,本文要解决的两大关键问题是:

  • 如何优化模型推理流水线来消除模型输入和输出之间的内存副本
  • 如何通过重新设计执行图来优化 GLMBlock 模块

构建 OpenVINO


stateful 模型实现显著优化

首先,需要分析 GLMBlock 层的结构,尝试封装一个类并按以下工作流来调用 OpenVINO

opset。接着,将图形数据序列化为 IR 模型 (.xml, .bin)。

图2 ChatGLM构建OpenVINO

stateful模型

关于如何构建 OpenVINO

stateful模型,以及如何使用OpenVINO

提供的模型创建样本,在 opset 构建模型,可参考文末文档。

ChatGLM 的自定义注意力机制是本文所关注和优化的部分。

主要思路是:构建全局上下文结构体,用于在模型内部追加并保存每一轮迭代后的 pastKV 的结果,这样减少了 pastKV 作为模型输入输出的拷贝开销,同时使用内联优化以实现 Rotary Embedding 和多头注意力机制 (Multi-Head Attentions)。

英特尔
®
AMX 是内置在第四代英特尔
®
至强
®
可扩展处理器中的矩阵乘法加速器,能够更快速地处理 bf16 或 int8 数据类型的矩阵乘加运算,通过加速张量处理,显著提高推理和训练性能。借助英特尔
®
AMX 内联指令(用于加速计算的单指令多操作),实现了对 ChatGLM 模型中 Attention,Rotary Embedding 等算子的高度优化,并且使用 bf16 指令进行乘加操作,在保证浮点指数位精度的同时提高运算效率。

与此同时,本方案还使用 int8 精度来压缩全连接层的权重,在实时计算中将使用bf16进行计算。因此,无需通过训练后量化 (PTQ) 或量化感知训练 (QAT) 对模型进行低精度处理。模型压缩方法可以降低模型存储空间,减少内存带宽的负载,因为计算仍然使用浮点,不会造成溢出,不会对模型精度造成损失。

为 ChatGLM 创建

OpenVINO™ stateful模型

请依照下方示例配置软硬件环境,并按照以下步骤优化 ChatGLM:

硬件要求

第四代英特尔
®
至强
®
可扩展处理器(代号 Sapphire Rapids)或其后续的、仍内置英特尔
®
AMX 的产品

软件验证环境

Ubuntu 22.04.1 LTS

面向 OpenVINO

Runtime Python API 的 Python 3.10.11

用于构建 OpenVINO

Runtime 的 GCC 11.3.0

cmake 3.26.4

构建 OpenVINO


源码

  • 安装系统依赖并设置环境
  • 创建并启用 Python 虚拟环境
$ conda create -n ov_py310 python=3.10 -y
$ conda activate ov_py310

△代码若显示不全,可左右滑动
  • 安装 Python 依赖
$ pip install protobuf transformers==4.30.2 cpm_kernels torch>=2.0 sentencepiece pandas
△代码若显示不全,可左右滑动
  • 使用 GCC 11.3.0 编译 OpenVINO
  • 克隆 OpenVINO

    并升级子模块
$ git clone https://github.com/luo-cheng2021/openvino.git -b luocheng/chatglm_custom
$ cd openvino && git submodule update --init --recursive

△代码若显示不全,可左右滑动
  • 安装 Python 环境依赖,以构建 Python Wheel
$ python -m pip install -U pip 
$ python -m pip install -r ./src/bindings/python/src/compatibility/openvino/requirements-dev.txt
$ python -m pip install -r ./src/bindings/python/wheel/requirements-dev.txt

△代码若显示不全,可左右滑动
  • 创建编译目录
$ mkdir build && cd build

△代码若显示不全,可左右滑动
  • 使用 CMake 编译 OpenVINO
$ cmake .. -DENABLE_LLMDNN=ON \
    -DBUILD_PYTHON_TESTS=ON \
    -DENABLE_CPU_DEBUG_CAPS=OFF \
    -DENABLE_DEBUG_CAPS=OFF  \
    -DCMAKE_BUILD_TYPE=Release \
    -DENABLE_INTEL_MYRIAD_COMMON=OFF \
    -DENABLE_INTEL_GNA=OFF \
    -DENABLE_OPENCV=OFF \
    -DENABLE_CPPLINT=ON \
    -DENABLE_CPPLINT_REPORT=OFF \
    -DENABLE_NCC_STYLE=OFF \
    -DENABLE_TESTS=ON \
    -DENABLE_OV_CORE_UNIT_TESTS=OFF \
    -DENABLE_INTEL_CPU=ON \
    -DENABLE_INTEL_GPU=OFF \
    -DENABLE_AUTO=OFF \
    -DENABLE_AUTO_BATCH=OFF \
    -DENABLE_MULTI=OFF \
    -DENABLE_HETERO=OFF \
    -DENABLE_INTEL_GNA=OFF \
    -DENABLE_PROFILING_ITT=ON\
    -DENABLE_SAMPLES=ON \
    -DENABLE_PYTHON=ON \
    -DENABLE_TEMPLATE=OFF  \
    -DENABLE_OV_ONNX_FRONTEND=OFF \
    -DENABLE_OV_PADDLE_FRONTEND=OFF \
    -DENABLE_OV_PYTORCH_FRONTEND=OFF \
    -DENABLE_OV_TF_FRONTEND=OFF \
    -DENABLE_OPENVINO_DEBUG=OFF \
    -DENABLE_CPU_DEBUG_CAPS=ON \
    -DCMAKE_INSTALL_PREFIX=`pwd`/install \
    -DCMAKE_INSTALL_RPATH=`pwd`/install/runtime/3rdparty/tbb/lib:`pwd`/install/runtime/3rdparty/hddl/lib:`pwd`/install/runtime/lib/intel64 \
    -Dgflags_Dir=`pwd`/../thirdparty/gflags/gflags/cmake
$ make --jobs=$(nproc --all)
$ make install

△代码若显示不全,可左右滑动
  • 安装针对 OpenVINO

    Runtime 和 openvino-dev 工具构建好的 Python Wheel
$ pip install ./install/tools/openvino*.whl

△代码若显示不全,可左右滑动
  • 检查系统 GCC 版本和 Conda Runtime GCC 版本。如下所示,如果系统 GCC 版本高于 Conda GCC 版本,请升级 Conda GCC 至相同版本,以满足 OpenVINO

    Runtime 的需求。(可选)
##check system (OpenVINO compiling env) gcc version
$ gcc --version
gcc (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0
##check conda python (runtime env for OpenVINO later) gcc version
$ python
Python 3.10.11 (main, May 16 2023, 00:28:57) [GCC 11.2.0] on linux
##If sys gcc ver > conda gcc ver, upgrade conda gcc ver -> sys gcc ver
$ conda install -c conda-forge gcc=11.3.0

△代码若显示不全,可左右滑动
  • 将 PyTorch 模型转为 OpenVINO

    IR
$ cd ..
$ python tools/gpt/gen_chatglm.py /path/to/pytorch/model /path/to/ov/IR

△代码若显示不全,可左右滑动

使用 OpenVINO


Runtime API 为 ChatGLM 构建推理流水线

本文提供了使用 Transformer 和 OpenVINO

Runtime API 构建推理流水线的样本。首先,在 test_chatglm.py 中,创建一个由 transformers.PreTrainedModel 衍生的新类。

然后,通过使用 OpenVINO

Runtime Python API 构建模型推理流水线来更新转发函数。其他成员函数则迁移自 modeling_chatglm.py
[2]
的 ChatGLMForConditionalGeneration。

如此一来,即可确保输入准备工作、set_random_seed、分词器/连接器 (tokenizer/detokenizer) 以及余下的流水线操作能够与原始模型的源码保持一致。

如需启用 int8 权重压缩,只需设置简单的环境变量 USE_INT8_WEIGHT=1。这是因为在模型生成阶段,已使用 int8 对全连接层的权重进行了压缩,因此模型可在之后的运行过程中直接使用 int8 权重进行推理,从而免除了通过框架或量化工具压缩模型的步骤。

请按照以下步骤使用 OpenVINO

Runtime 流水线测试 ChatGLM:

  • 运行 bf16 模型
$ python3  tools/gpt/test_chatglm.py /path/to/pytorch/model /path/to/ov/IR --use=ov
△代码若显示不全,可左右滑动
  • 运行 int8 模型
$ USE_INT8_WEIGHT=1 python test_chatglm.py /path/to/pytorch/model /path/to/ov/IR --use=ov

△代码若显示不全,可左右滑动

权重压缩:降低内存带宽使用率,提升推理速度

本文采用了 Vtune 对模型权重数值精度分别为 bf16 和 int8 的内存带宽使用率(图 3 和图 4)以及 CPI 率进行了性能对比分析(表 1)。结果发现:当模型权重数值精度压缩至 int8 时,可同时降低内存带宽使用率和 CPI 率。

图3 模型权重数值精度为 bf16 时的内存带宽使用率
图4 模型权重数值精度为 int8 时的内存带宽使用率
表1 采用不同模型权重数值精度时的 CPI 率

每条指令消耗的时钟周期 (Clockticks per Instruction Retired, CPI) 事件率,也称为“平均指令周期数 (Cycles per Instruction)”,是基于硬件事件抽样收集的基础性能指标之一,在抽样模式下也称为“性能监控计数器 (PMC) 分析”。

该比率计算方式为:用处于非停机状态的处理器时钟周期数 (Clockticks) 除以已消耗指令数。每个处理器用于计算时钟周期数和已消耗指令数的确切事件可能并不相同,但 VTune Profiler 可辨别和使用正确的数量。

CPI < 1 时,通常为采用指令密集型代码的应用,而 CPI > 1 则可能是停滞时钟周期密集型应用,也可能是内存密集型应用。

由此,我们可以得出结论,类似 chatGLM 等语言模型对内存带宽的要求非常高,性能往往受到内存操作或带宽的限制。

很多场景下,消除内存操作的负载,性能会因此获得大幅收益。在优化此类模型时,如何在不影响精度的同时对模型进行压缩或轻量化处理是一项不可或缺的技巧。除此之外,在异构平台和框架上进行部署,还涉及到减少内存/设备存储之间的数据搬运等优化思路。

因此,在压缩模型的同时,还需要考虑对原始 pytorch 模型推理 forward/generates 等函数流水线的优化,而 OpenVINO

在优化模型自身的同时,还将流水线的优化思路体现在修改模型结构中(将 KV cache保存在模型内部),通过优化 Optimum-intel 等框架的流水线,减少内存拷贝和数据搬运。

结论

笔者根据上述方法重新设计执行图并优化了 GLMBlock,消除了 ChatGLM 模型输入和输出之间的内存副本,且模型运行高效。

随着 OpenVINO

的不断升级,本方案的优化工作也将得到推广并集成至正式发布的版本中。这将有助于扩展更多的大语言模型用例。敬请参考 OpenVINO

官方版本
[6]
和 Optimum-intel OpenVINO

后端
[7]
,获取有关大语言模型的官方高效支持。

了解更多内容,请点击文末【阅读原文】。

作者简介:

英特尔
®
OpenVINO

开发工具客户支持工程师赵桢和邹文艺,英特尔
®
OpenVINO

开发工具 AI 框架工程师罗成和李亭骞,都在从事 AI 软件工具开发与优化工作。

OpenVINO

stateful模型构建:

https://docs.openvino.ai/2022.3/openvino_docs_OV_UG_network_state_intro.html

通过 opset 构建模型:

https://github.com/openvinotoolkit/openvino/blob/master/samples/cpp/model_creation_sample/main.cpp

参考链接:

[1]https://www.intel.cn/content/www/cn/zh/events/accelerate-with-xeon.html

[2]https://huggingface.co/THUDM/chatglm-6b/blob/main/modeling_chatglm.py

[3]https://huggingface.co/THUDM/chatglm-6b/blob/main/modeling_chatglm.py#L1031

[4]https://huggingface.co/THUDM/chatglm-6b/blob/main/modeling_chatglm.py#L554

[5]https://huggingface.co/THUDM/chatglm-6b/blob/main/config.json

[6]https://www.intel.cn/content/www/cn/zh/developer/tools/openvino-toolkit/overview.html

[7]https://huggingface.co/docs/optimum/main/en/intel/index

*本文系量子位获授权刊载,观点仅为作者所有。

最“in”大模型专栏

1

十亿参数,一键瘦身!「模型减重」神器让大模型狂掉3/4

2

保护大模型应用安全,现在不需要拿性能做代价了

3

如何优化ChatGLM-6B?一行代码就行

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

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

相关文章

Echarts 问题集锦

最近公司集中做统计图表&#xff0c;新手小白&#xff0c;真被Echarts折腾地不轻&#xff0c;怕自己年老记忆衰退&#xff0c;特地做一些记录。以备后面查阅。 1、X轴的 数据显示不全&#xff0c;间或不显示 很奇葩&#xff0c;我发现数据里有一个值为0.0&#xff0c;当这条记…

Windows 解决文件包含病毒或潜在的垃圾软件

注意确保软件没问题&#xff0c;保护个人数据隐私 问题描述 解决步骤

科普文:一文搞懂jvm原理(三)执行引擎之垃圾回收器

概叙 科普文&#xff1a;一文搞懂jvm(一)jvm概叙-CSDN博客 科普文&#xff1a;一文搞懂jvm原理(二)类加载器-CSDN博客 科普文&#xff1a;一文搞懂jvm原理(三)执行引擎-CSDN博客 科普文&#xff1a;一文搞懂jvm原理(四)运行时数据区-CSDN博客 前面我们介绍了jvm&#xff0c…

基于java+springboot+vue实现的电影院购票系统(文末源码+Lw)274

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装电影院购票系统软件来发挥其高效地信息处理的作用&#xf…

Flink 容错机制

一致性检查点&#xff08;checkpoint&#xff09; 什么是 Checkpoint &#xff1f; Flink 故障恢复机制的核心&#xff0c;就就是应用状态的一致性检查点&#xff1b;有状态流应用的一直检查点&#xff0c;其实就是所有任务的状态&#xff0c;在某一时间点的一份拷贝&#xff…

月之暗面kimi底层推理系统原理

太长不看版&#xff08;作者大佬自己的在知乎碎碎念&#xff09;&#xff1a; 本论文与很多 Prefill/Decoding 分离的论文不同的是&#xff0c;这套方案已经在大规模集群上进行几个月的验证并证明了方案的有效性。目前这套系统承载了 Kimi 线上80% 以上的流量&#xff0c; 效果…

(18)GPS/指南针(一)

文章目录 前言 1 GPS/指南针 2 RTK GPS 3 GPS驱动程序选项 4 GPS自动切换 5 高级用途 前言 Copter/Plane/Rover 支持与 GPS、指南针和其他定位技术的整合&#xff1a; 1 GPS/指南针 Avionics Anonymous GNSS CompassAvionics Anonymous CompassBeitain BN-220 GPS / B…

《梦醒蝶飞:释放Excel函数与公式的力量》8.1 COUNT函数

8.1 COUNT函数 在Excel中&#xff0c;COUNT函数及其相关变体用于统计单元格中的数据量。它们能够帮助我们快速统计数据的数量&#xff0c;常用于数据分析和报表制作。 8.1.1 函数简介 COUNT函数用于统计指定区域内的数值单元格数量。它只统计数值&#xff0c;不包括文本或空…

XD3C03P1G、XD3C01N3F比例方向控制阀放大板

XD3A01N2G、XD3A03N2G、XD3C03N1F、XD3C03P1G、XD3C01N3F、XD3C03N2F、XD3C01P4G、XD3C03P3G、XD3C03N2F、XD3C03N2G、XDP3A01P1F、XDP3C03N2G、XDP3A03P3G、XDP3C01NAF、XDP3C03P6G、XDP3A03PAG、XDP3A03N3F液压比例方向阀是液压系统中的关键元件&#xff0c;用于实现对流量、…

二叉树的右视图-二叉树

199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 层序遍历&#xff0c;广度优先 queue先进后出&#xff0c;每层从左往右进树&#xff0c;最后一个就是最右边的数&#xff1b;pop掉这层的。push下一层&#xff1b; class Solution { public:vector<int> r…

考研生活day2--王道课后习题2.3.1、2.3.2、2.3.3

2.3.1 题目描述&#xff1a; 这题和曾经做过的LeetCode203.移除元素一模一样&#xff0c;所以我们就使用LeetCode进行书写&#xff0c;题目链接203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 解题思路 大家的第一反应肯定是根据书上所学的书写方法一样书写&…

【linux网络(七)】数据链路层详解

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux网络 1. 前言2. 认识MAC…

C++视觉开发 三.缺陷检测

一.距离变换 1.概念和功能 距离变换是一种图像处理技术&#xff0c;用于计算图像中每个像素到最近的零像素&#xff08;背景像素&#xff09;的距离。它常用于图像分割、形态学操作和形状分析等领域。它计算图像中每个像素到最近的零像素&#xff08;背景像素&#xff09;的距…

CAM350删除铺铜?

CAM350删除铺铜&#xff1f; 1、选择菜单栏Add 2、选择Polygon Void→Line... 3、然点击需要操作的铜箔&#xff0c;使其高亮 4、用鼠标框选需要删除的部分&#xff0c;然后右击 5、删除后如下图所示 The Layer Bar controls are part of the new Navigation Pane and can also…

dledger原理源码分析系列(一)-架构,核心组件和rpc组件

简介 dledger是openmessaging的一个组件&#xff0c; raft算法实现&#xff0c;用于分布式日志&#xff0c;本系列分析dledger如何实现raft概念&#xff0c;以及dledger在rocketmq的应用 本系列使用dledger v0.40 本文分析dledger的架构&#xff0c;核心组件&#xff1b;rpc组…

MySQL 9.0创新版发布!功能又进化了!

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

Runway:Gen-3 Alpha 文生视频现已开放

Runway 自 6 月 17 号公布 Gen-3 Alpha 快半个月了, 现在终于对所有人开放了&#xff0c;当然前提是你至少订阅了标准版&#xff08;12 美刀/月), 传送门&#xff1a;runwayml.com

【CSS in Depth 2 精译】2.3 告别像素思维

当前内容所在位置 第一章 层叠、优先级与继承第二章 相对单位 2.1 相对单位的威力 2.1.1 响应式设计的兴起 2.2 em 与 rem 2.2.1 使用 em 定义字号2.2.2 使用 rem 设置字号 2.3 告别像素思维 ✔️2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性2.7 本章小结 2.3 告别…

电脑IP地址自动获取:操作指南与优势分析

在数字化时代&#xff0c;网络连接已成为我们日常生活和工作中的重要组成部分。而在建立网络连接的过程中&#xff0c;IP地址的设置无疑是至关重要的一环。IP地址&#xff0c;作为网络设备的唯一标识&#xff0c;其设置方式直接影响到网络的稳定性和安全性。本文将详细介绍如何…

充气膜羽毛球馆投资需要多少钱—轻空间

充气膜羽毛球馆是一种现代化的运动设施&#xff0c;以其灵活的结构设计和高效的能耗管理受到广泛关注。投资建设一个充气膜羽毛球馆&#xff0c;涉及多个方面的成本&#xff0c;包括基础建设、膜材选择、系统配置以及运营维护费用。轻空间将详细分析投资建设充气膜羽毛球馆的成…