当前位置:   article > 正文

上海人工智能实验室的书生·浦语大模型学习笔记及作业--day5_上海人工智能实验室 大模型部署工具

上海人工智能实验室 大模型部署工具

书生·浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,这次有机会参与试用,特记录每日学习情况。

在医院的走廊,护士来来往往,家人在里面,我在走廊。难得病房门口有个小桌子,旁边放着一堆宣传资料。可能原本只是为了放宣传资料,但为了做成一个宣传角,凑了一个桌子两把凳子,看着像那么回事。没想到现在被人意外发现了它办公学习的作用。

今天学习的是模型部署。

一、什么是模型部署

1、定义

模型部署是指将训练好的模型在特定环境中运行的过程,以便将其应用到实际生产中。这个过程需要解决模型框架兼容性和运行速度的问题。

2、组成

在部署阶段,模型需要根据需求进行优化和调整,以便更好地适应实际应用场景。常见的模型部署流水线包括深度学习框架、中间表示和推理引擎等。

3、目标

模型部署的目标是将模型以一种客户可以使用的方式进行组织和呈现,以便在实际应用中使用。在模型发布之前,需要将模型从训练环境中导出,然后将其部署到生产环境中,通常是以服务或库的形式提供给用户使用。

4、技巧

技术方案包括模型并行、低比特量化、transformer的缓存优化等。

在云端,常见的方案包括deepspeed、tensorrt-llm、VllM等,而在移动端,代表性的方案包括llama.cpp和指mlc-llm

知识蒸馏:大模型的训练通常采用知识蒸馏技术,首先训练一个更大的教师模型,然后使用教师模型指导一个较小的学生模型训练。这样可以加速训练过程并保留大模型的能力。

模型剪枝与压缩:为了减小大模型大小和降低推理成本,通常需要对模型进行剪枝、量化和压缩等处理。

二、什么是LMDeploy

LMDeploy是一个用于部署大模型的工具箱,由上海人工智能实验室开发。它使用C++/CUDA进行推理,并对外提供Python/gRPC/HTTP接口和WebUI界面。LMDeploy支持tensor parallel分布式推理,并支持fp16/weightint4/kv cache int8量化。LMDeploy的核心功能包括量化、TurboMind和推理服务。

LMDeploy使用MIT HAN LAB开源的AWQ算法,将原模型量化为4bit模型。AWQ算法是一种在矩阵或模型推理过程中,一小部分重要参数可以不量化的算法。相较于GPTQ算法,AWQ算法的推理速度更快,量化的时间更短。

推理时,先把4bit权重反量化为FP16,一小部分重要参数的计算依旧使用的是FP16。

LMDeploy还具有以下特点和优势:

支持多种大模型结构和算法,如transformer结构(例如LLaMA、LLaMa2、InternLM、Vicuna等)。

在静态和动态推理上具有较高的进度和速度。

采用AWQ算法进行缓存密集型量化,能够保留数据的重要部分,不重要的部分进行量化,以保持性能并减少显存使用。

提供了多GPU部署和量化的支持,以便更好地利用计算资源。

提供了丰富的工具和库,方便用户进行模型部署和管理。

1、两种推理方式

静态推理和动态推理是两种不同的推理方式。

在静态推理中,模型的输入和输出长度是固定的,因此性能相对稳定。静态推理通常在小batch下具有较高的性能,因为其计算和内存访问模式相对固定,可以利用优化工具进行更好的优化。然而,随着batch的增大,静态推理的加速效果可能会逐渐减弱。

动态推理则不同,其输入和输出长度是不定的,因此需要进行一些额外的处理来处理变长数据。动态推理通常需要使用更多的计算资源,因为需要根据不同的输入长度进行不同的计算。但是,动态推理在处理真实对话等变长数据时具有更好的性能,因为其可以更好地处理各种长度的输入。

在LMDeploy中,静态和动态推理的性能都有所提升。LMDeploy采用了量化技术,可以减小显存占用并提升运行速度。对于静态推理,LMDeploy在小batch下性能是fp16的两倍,batch越大加速效果越不明显。对于动态推理,LMDeploy的精度优于其他vLLM框架。

2、量化

量化是一种减少模型大小和推理时间的技术,通过将模型参数转换为较低精度的表示,可以显著减少存储和内存需求,同时保持较高的推理性能。

在LMDeploy中,使用MIT HAN LAB开源的AWQ算法进行量化(仅针对参数权重进行量化),可以将4bit权重反量化回FP16进行计算,相较于社区使用较多的GPTQ算法,AWQ的推理速度更快,量化的时间更短。同时,LMDeploy还支持多种量化方法、推理引擎以及接口等,可以满足不同应用场景的需求。

通过量化技术,LMDeploy可以减小显存占用并提升运行速度,从而提高推理性能。在静态推理中,LMDeploy在小batch下性能是fp16的两倍,batch越大加速效果越不明显。在动态推理中,LMDeploy的精度优于其他vLLM框架。

量化的两个概念

  • 计算密集(compute-bound): 指推理过程中,绝大部分时间消耗在数值计算上;针对计算密集型场景,可以通过使用更快的硬件计算单元来提升计算速。
  • 访存密集(memory-bound): 指推理过程中,绝大部分时间消耗在数据读取上;针对访存密集型场景,一般通过减少访存次数、提高计算访存比或降低访存量来优化。

常见的 LLM 模型由于 Decoder Only 架构的特性,实际推理时大多数的时间都消耗在了逐 Token 生成阶段(Decoding 阶段),是典型的访存密集型场景。

我们可以使用 KV Cache 量化和 4bit Weight Only 量化(也就是W4A16,或者简称为参数量化)。KV Cache 量化是指将逐 Token(Decoding)生成过程中的上下文 K 和 V 中间结果进行 INT8 量化(计算时再反量化),以降低生成过程中的显存占用。4bit Weight 量化,将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本。Weight Only 是指仅量化权重,数值计算依然采用 FP16(需要将 INT4 权重反量化)。

KV Cache 量化

KV Cache 量化是将已经生成序列的 KV 变成 Int8,使用过程一共包括三步:

第一步:计算 minmax。主要思路是通过计算给定输入样本在每一层不同位置处计算结果的统计情况。

  • 对于 Attention 的 K 和 V:取每个 Head 各自维度在所有Token的最大、最小和绝对值最大值。对每一层来说,上面三组值都是 (num_heads, head_dim) 的矩阵。这里的统计结果将用于本小节的 KV Cache。
  • 对于模型每层的输入:取对应维度的最大、最小、均值、绝对值最大和绝对值均值。每一层每个位置的输入都有对应的统计值,它们大多是 (hidden_dim, ) 的一维向量,当然在 FFN 层由于结构是先变宽后恢复,因此恢复的位置维度并不相同。这里的统计结果用于下个小节的模型参数量化,主要用在缩放环节。

第一步执行命令如下:

  1. # 计算 minmax
  2. lmdeploy lite calibrate \
  3. --model /root/share/temp/model_repos/internlm-chat-7b/ \
  4. --calib_dataset "c4" \
  5. --calib_samples 128 \
  6. --calib_seqlen 2048 \
  7. --work_dir ./quant_output

在这个命令行中,会选择 128 条输入样本,每条样本长度为 2048,数据集选择 C4,输入模型后就会得到上面的各种统计值。值得说明的是,如果显存不足,可以适当调小 samples 的数量或 sample 的长度。

第二步:通过 minmax 获取量化参数。主要就是利用下面这个公式,获取每一层的 K V 中心值(zp)和缩放值(scale)。

  1. zp = (min+max) / 2
  2. scale = (max-min) / 255
  3. quant: q = round( (f-zp) / scale)
  4. dequant: f = q * scale + zp

有这两个值就可以进行量化和反量化操作了。具体来说,就是对历史中存储的K和V进行量化,使用时再做反量化。执行命令如下:

  1. # 通过 minmax 获取量化参数
  2. lmdeploy lite kv_qparams \
  3. --work_dir ./quant_output \
  4. --turbomind_dir workspace/triton_models/weights/ \
  5. --kv_sym False \
  6. --num_tp 1

在这个命令中,num_tp 的含义前面介绍过,表示 Tensor 的并行数。每一层的中心值和缩放值会存储到 workspace 的参数目录中以便后续使用。kv_sym 为 True 时会使用另一种(对称)量化方法,它用到了第一步存储的绝对值最大值,而不是最大值和最小值。

第三步:修改配置。也就是修改 weights/config.ini 文件。

  1. tensor_para_size = 1
  2. session_len = 2056
  3. max_batch_size = 64
  4. max_context_token_num = 1
  5. step_length = 1
  6. cache_max_entry_count = 0.5
  7. cache_block_seq_len = 128
  8. cache_chunk_size = 1
  9. use_context_fmha = 1
  10. quant_policy = 0
  11. max_position_embeddings = 2048
  12. rope_scaling_factor = 0.0
  13. use_logn_attn = 0
  • KV int8 开关:
    • 对应参数为 quant_policy,默认值为 0,表示不使用 KV Cache,如果需要开启,则将该参数设置为 4。
    • KV Cache 是对序列生成过程中的 K 和 V 进行量化,用以节省显存。
    • 当显存不足,或序列比较长时,建议打开此开关。

接下来就可以正常运行前面的各种服务了,只不过咱们现在可是用上了 KV Cache 量化,能更省(运行时)显存了。

KV Cache 可以节约大约 20% 的显存。KV Cache 量化既能明显降低显存占用,还有可能同时带来精准度(Accuracy)的提升。

W4A16 量化

第一步:同 KV Cache 量化,也是要计算 minmax。

第二步:量化权重模型。利用第一步得到的统计值对参数进行量化,具体又包括两小步:

  • 缩放参数。主要是性能上的考虑。
  • 整体量化。

第二步的执行命令如下:

  1. # 量化权重模型
  2. lmdeploy lite auto_awq \
  3. --model /root/share/temp/model_repos/internlm-chat-7b/ \
  4. --w_bits 4 \
  5. --w_group_size 128 \
  6. --work_dir ./quant_output

命令中auto_awq就是指用AWQ算法进行量化。w_bits 表示量化的位数,w_group_size 表示量化分组统计的尺寸(一般使用这个默认值,不去更改),work_dir 是量化后模型输出的位置。

这里需要特别说明的是,因为没有torch.int4,所以实际存储时,8个 4bit 权重会被打包到一个 int32 值中。所以,如果你把这部分量化后的参数加载进来就会发现它们是 int32 类型的。

第三步:转换成 TurboMind 格式。

  1. # 转换模型的layout,存放在默认路径 ./workspace 下
  2. lmdeploy convert internlm-chat-7b ./quant_output \
  3. --model-format awq \
  4. --group-size 128

model-format的参数awq就是指用AWQ算法进行量化。 group-size 就是上一步的那个 w_group_size。如果不想和之前的 workspace 重复,可以指定输出目录:--dst_path,比如:

  1. lmdeploy convert internlm-chat-7b ./quant_output \
  2. --model-format awq \
  3. --group-size 128 \
  4. --dst_path ./workspace_quant

这就可以正常运行前面的各种服务了,不过咱们现在用的是W4A16量化后的模型。

W4A16 参数量化后能极大地降低显存,同时相比其他框架推理速度具有明显优势。

W4A16量化和 KV Cache 量化也可以一起使用,以达到最大限度节省显存。

实操经验

量化在降低显存的同时,一般还能带来性能的提升,因为更小精度的浮点数要比高精度的浮点数计算效率高,而整型要比浮点数高很多。

在各种配置下尝试,看效果能否满足需要。这一般需要在自己的数据集上进行测试。具体步骤如下。

  • Step1:优先尝试正常(非量化)版本,评估效果。
    • 如果效果不行,需要尝试更大参数模型或者微调。
    • 如果效果可以,跳到下一步。
  • Step2:尝试KV Cache 量化版本,评估效果。
    • 如果效果不行,回到上一步。
    • 如果效果可以,跳到下一步。
  • Step3:尝试W4A16量化版本,评估效果。
    • 如果效果不行,回到上一步。
    • 如果效果可以,跳到下一步。
  • Step4:尝试W4A16+ KV Cache 量化,评估效果。
    • 如果效果不行,回到上一步。
    • 如果效果可以,使用方案。

根据实践经验,一般情况下:

  • 精度越高,显存占用越多,推理效率越低,但一般效果较好。
  • Server 端推理一般用非量化版本或半精度、BF16、Int8 等精度的量化版本,比较少使用更低精度的量化版本。
  • 端侧推理一般都使用W4A16量化版本,且大多是低精度的量化版本。这主要是因为计算资源所限。

3、TurboMind

它是基于英伟达的FasterTransformer研发而成的一款关于LLM推理的高效推理引擎。其主要功能包括支持LLaMa结构模型、persistent batch推理模式和可扩展的KV缓存管理器。并具有持续批处理、有状态推理、k/v缓存块和高性能算子融合等特性。

TurboMind的设计目标是在保持高性能的同时,提供灵活性和可扩展性。它采用了多种优化技术,如算子融合、内存优化等,以提高推理速度和效率。此外,TurboMind还支持多种精度的推理,包括FP32、FP16和INT8等,以满足不同应用场景的需求。

通过TurboMind推理引擎,LMDeploy可以实现高效、准确的推理服务,支持大规模的模型部署和应用。它提供了丰富的接口和工具,方便用户进行模型推理和管理。

实操经验

首先说 “模型推理/服务”,推荐使用 TurboMind,使用简单,性能良好,相关的 Benchmark 对比如下。

上面的性能对比包括两个场景:

  • 场景一(前4张图):固定的输入、输出 token 数(分别1和2048),测试Token输出吞吐量(output token throughput)。
  • 场景二(第5张图):使用真实数据,测试吞吐量(request throughput)。

场景一中,BatchSize=64时,TurboMind 的吞吐量超过 2000 token/s,整体比 DeepSpeed 提升约 5% - 15%;BatchSize=32时,比 Huggingface 的Transformers 提升约 3 倍;其他BatchSize时 TurboMind 也表现出优异的性能。

场景二中,对比了 TurboMind 和 vLLM 在真实数据上的吞吐量(request throughput)指标,TurboMind 的效率比 vLLM 高 30%。

4、推理服务

包括api server、gradion、triton inferenceserver等,提供了灵活的推理服务解决方案。

后面的 API 服务和 Client 就得分场景了。

  • 我想对外提供类似 OpenAI 那样的 HTTP 接口服务。推荐使用 TurboMind推理 + API 服务(2.3)。
  • 我想做一个演示 Demo,Gradio 无疑是比 Local Chat 更友好的。推荐使用 TurboMind 推理作为后端的Gradio进行演示(2.4.2)。
  • 我想直接在自己的 Python 项目中使用大模型功能。推荐使用 TurboMind推理 + Python(2.5)。
  • 我想在自己的其他非 Python 项目中使用大模型功能。推荐直接通过 HTTP 接口调用服务。也就是用本列表第一条先启动一个 HTTP API 服务,然后在项目中直接调用接口。

三、基础作业

使用 LMDeploy 以本地对话、网页Gradio、API服务中的一种方式部署 InternLM-Chat-7B 模型,生成 300 字的小故事

1、部署模型InternLM-Chat-7B

2、以本地对话生成 300 字的小故事

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/667118
推荐阅读
相关标签
  

闽ICP备14008679号