本文以书生浦语平台(书生·浦语)为例,简单说明如何快速实现Llama 3 高效部署实践(LMDeploy版)
参考资料:
https://github.com/kv-chiu/Llama3-Tutorial
=============目录============
一、总体步骤
二、可能遇到的问题
三、测试效果
四、部分Q&A
=============正文============
一、总体步骤
参考https://github.com/kv-chiu/Llama3-Tutorial/blob/main/docs/lmdeploy.md
不赘述
二、可能遇到的问题
1.显存大小问题。启动llama3(且未量化的情况下)一般必须22G的内存,如果不够就会报错out of memory。
备注说明:
即使量化后,比如使用了上述教程量化的步骤后,大模型下降到6G显存的开销(在云端用8g显存),但实际效果仍然受影响。从下图可以看到,第一次问答还正常,但从第二次的问题开始,已经无法正常回答了。
再试一遍,仍然如此。如下。
2.环境问题。比如之前conda新建了名为“lmdeploy”的环境,但不明原因下再次打开后运行部署命令就报错了。比如会针对之前安装成功的python、lmdeploy、pytorch等库报错,重装后仍然无法解决一连串的环境问题。
解决方法:conda另外新建一个环境。旧的环境可以考虑清除。
三、测试效果
上述操作步骤的描述,是理想情况。实际操作时,有可能看到其他效果。
以在internstudio(24g显存)的环境为例。
- --cache-max-entry-count参数,设为0.5和0.01,效果差距不是很大
设为0.5,如图,显存消耗在16-20g之间。重复试了一遍,情况大致相同。
设为0.1时,模型启动稍微变慢,但gpu只调整到16g。输入prompt后,稳定在17g。如图
2.上述--cache-max-entry-count参数,设为0.5和0.01时,还有个比较奇怪的现象,就是启动lmdeploy命令刚开始时显存消耗是下降了,但过一会儿有时甚至是1、2秒,就瞬间回到用满显存(该云端配置一般用到22g)的情况。而下面2个参数的情况则不会出现这种波动
1)跑命令lmdeploy chat /root/model/Meta-Llama-3-8B-Instruct_4bit --model-format awq,显存消耗如图
2)跑命令lmdeploy chat /root/model/Meta-Llama-3-8B-Instruct_4bit --model-format awq --cache-max-entry-count 0.01,显存消耗如图
初步分析:
在大模型量化部署中,--cache-max-entry-count 参数通常用于控制键值对(Key-Value,简称KV)缓存的大小,这个缓存用于存储解码器在生成文本时所需的中间结果。当设置较小的 --cache-max-entry-count 值时,比如0.5或0.01,缓存能够存储的条目数量将受到限制,这可能会影响模型的推理速度和显存使用。
以下是可能的原因:
1. 显存消耗波动:
-
- 当设置 --cache-max-entry-count 为0.5时,虽然初始时显存消耗有所下降,但模型在推理过程中可能会生成大量的中间结果,这些结果需要被存储在缓存中。如果缓存大小不足以容纳所有中间结果,那么模型可能会频繁地进行缓存替换,这可能导致显存使用的波动。特别是当模型处理较长的输入或生成较长的输出时,这种波动可能更加明显。
- 另外,模型的某些部分(如注意力机制)可能需要访问大量的显存来进行计算。如果这部分计算没有得到有效的优化或并行化,那么显存使用也可能出现波动。
2. 稳定性差异:
-
- 在第二个命令中,使用了 --model-format awq 参数。AWQ(Asymmetric Weight Quantization)是一种量化技术,用于减小模型的大小和提高推理速度。当使用AWQ量化后的模型时,模型的参数和计算都会被优化,从而减少了显存的使用。这可能是为什么第二个命令在显存使用上更加稳定的原因。
- 另外,当设置 --cache-max-entry-count 为0.01时,几乎禁用了KV缓存。这意味着模型在推理过程中不会存储太多的中间结果,从而减少了显存使用的波动。但是,这可能会降低模型的推理速度,因为模型需要频繁地重新计算这些中间结果。
为了解决这个问题,可以考虑尝试以下方法:
- 优化模型:使用更先进的量化技术或模型压缩方法来减小模型的大小和提高推理速度。
- 调整缓存大小:尝试使用不同的 --cache-max-entry-count 值来找到显存使用和推理速度之间的最佳平衡点。
- 并行化计算:如果可能的话,尝试使用并行计算来加速模型的推理过程,并减少显存使用的波动。
- 监控显存使用:使用工具来监控显存的使用情况,以便更好地理解问题的根源并找到解决方案。
(其余参考资料:[lmdeploy 0.4.1] & [多模态]新SoTA [InternVL-Chat-V1.5]实践[InternVL] - 知乎)
3.用了量化后,虽然降低了显存,但推理出现问题。第一次问答正常,但第二次后就无法正常输出回答,没有回答内容。
再试一遍,仍然如此
四、部分Q&A
1. 步骤说明中,“lmdeploy lite auto_awq \
/root/model/Meta-Llama-3-8B-Instruct \
--calib-dataset 'ptb' \
--calib-samples 128 \
--calib-seqlen 1024 \
--w-bits 4 \
--w-group-size 128 \
--work-dir /root/model/Meta-Llama-3-8B-Instruct_4bit“
这句命令是什么意思?
答:这条命令是执行模型量化的命令,具体来说,它是针对某种模型部署工具(可能是lmdeploy)的命令,用于将模型进行量化处理。
- lmdeploy lite auto_awq:调用lmdeploy工具的lite子命令,并执行auto_awq(可能是自动权重量化)功能。
- /root/model/Meta-Llama-3-8B-Instruct:指定了要量化的模型路径。
- --calib-dataset 'ptb':指定用于校准的数据集为'ptb'。
- --calib-samples 128:在校准过程中使用的样本数量是128。
- --calib-seqlen 1024:校准数据的序列长度为1024。
- --w-bits 4:使用4位来表示模型的权重。
- --w-group-size 128:可能是指定权重分组的大小,这在某些量化策略中用于提高量化的效率和准确性。
- --work-dir /root/model/Meta-Llama-3-8B-Instruct_4bit:指定工作目录,量化后的模型或其他输出文件可能会保存在这个目录中。
量化(Quantization)是一种模型优化技术,主要用于减小模型的大小和提高模型的推理速度,尤其是在边缘设备或资源有限的设备上。简单来说,量化就是将模型的权重和激活从浮点数转换为较低精度的整数(例如8位、4位等)。这样做的好处是可以显著减少模型的存储需求和计算复杂性,但可能会以牺牲一定的模型精度为代价。
在这个命令中,模型被量化为4位,这意味着模型的权重和激活将被转换为4位整数,从而大大减少了模型的大小和计算复杂性。但这也可能导致模型的精度有所下降,因此在校准过程中会使用一个数据集来确保量化后的模型仍然保持良好的性能。
2.能否简单介绍下量化?
3. API页面中,看到有GET和POST两种结构,可否简单说下?
答:无论是GET还是POST,它们都是HTTP协议中的请求方法,用于你从客户端(如Web浏览器、API调用者等)向服务器发送请求。这两种方法之间的主要区别体现在它们的用途、语义和传输的数据方式上。
- 用途和语义:
-
- GET方法通常用于请求数据。它通常用于获取(检索)资源,比如从数据库中查询数据,或者获取网页的内容。GET请求是幂等的,即多次相同的GET请求不会改变服务器上的资源状态。
- POST方法通常用于发送数据到服务器以创建或更新资源。例如,提交表单数据、上传文件或者发送JSON数据给API来执行某些操作。POST请求不是幂等的,因为每次发送POST请求都可能会改变服务器上的资源状态。
- 传输的数据:
-
- GET请求的数据通常附加在URL的查询字符串中,以键值对的形式出现(例如,http://example.com/search?q=llama3)。由于URL长度有限制,所以GET请求能携带的数据量也有限。
- POST请求的数据则包含在请求体中。这意味着可以发送大量的数据,包括文件上传和复杂的JSON结构。POST请求体中的数据格式可以由Content-Type头指定,常见的格式有application/x-www-form-urlencoded(用于表单提交)、multipart/form-data(用于文件上传)和application/json(用于发送JSON数据)。
- 缓存和安全性:
-
- 由于GET请求通常用于获取数据,因此它们可以被缓存。这可以提高性能,因为相同的GET请求可能不需要每次都从服务器获取数据。但是,这也意味着GET请求中的数据(即URL查询字符串)可能会被记录在历史记录、服务器日志或浏览器缓存中,这可能会带来安全或隐私方面的问题。
- POST请求通常不被缓存,因为它们是用于发送数据的。此外,由于POST请求的数据在请求体中,而不是在URL中,所以它们通常被认为比GET请求更安全,因为它们不会将数据暴露在URL中。
- 幂等性:
-
- 如前所述,GET请求是幂等的,而POST请求通常不是。这意味着多次相同的GET请求不会改变服务器上的资源状态,而多次相同的POST请求可能会导致资源的多次创建或更新。
- 浏览器行为:
-
- 在浏览器中,直接输入一个URL或点击一个链接通常会发送一个GET请求。而提交一个HTML表单时,表单的method属性可以指定为GET或POST