背景
目前在公司内部4张A10的GPU服务器上部署了ChatGLM3开源模型;然后部署了官方默认的web_demo[1]、api_demo[2]两种模式;重新设计了前端,支持H5和安卓两个客户端调用。但却发现了不能并发访问的问题。
问题现象
在安卓与H5同时调用ChatGLM的API接口(流式接口)时,其中有一个客户端的返回是正常的,而另一个客户端返回却是乱码(解码后是空数据),同时模型报错。报错内容与问题请看issue[3]。官方回复如下:后来我测试用多卡部署模型,比如3卡,此时可以支持3个以下的用户调用,但再多就不行了。
问题分析
由于非AI相关科班出身也不是专门做这个的,因此一下子还有点棘手;后来在智谱AI开放平台的使用指南-速率限制指南[4] 一文中,发现其支持并发调用,只是说有并发数限制。因此我分析来说,应该是放出来的模型与开放平台上的模型有一定的区别,而这个区别就在于模型的并发能力。毕竟外部API调用时,最终还是调用模型内部的流式接口/非流式接口。也就是说,这个模型内部的接口并不支持并行计算。
从模型的内部来说,其是transformer神经网络结构,但其并发能力却没有这么简单,毕竟模型涉及到的计算量是巨大的。归根来说,还是transformer的并行计算能力。
后来找到个遇到同样情况的博文,不过和我们的部署方式还是有区别的。mosec部署chatglm2-6B[5] 一文中分析了下其遇到的问题与解决方案,至此我大概也清楚了并发调用模型API时为什么会返回乱码(空数据)。
原因与解决策略
当并发调用时,其中模型已经处理完了一个request后,返回的tensor识别了eos_token,模型会认为已经处理完了所有的request,因此返回空数据。
那么从这里来说的话,我暂时想到的解决策略:模型内部按batch来处理request。
这个代码不好改,应该有开源的实现和解决策略。后来我又想到了LLaMA-Factory这个微调框架,他们也是有api_demo的,应该也会遇到这样的问题,因此提了个Issue,还好最终有另外的解,见issue[6]。
LLaMA-Factory官方通过vllm实现了并发流式,暂时还没验证,简单看了下代码,理论上是冒得问题的:
vLLM推理框架是一种用于大规模语言模型(Large Language Models, LLMs)的推理加速技术。它的主要目的是提高语言模型的推理速度,从而使得LLMs能够更快速地响应用户的查询。以下是一些关于vLLM推理框架的关键点:
-
分区(Partitioning):vLLM推理框架通过将大型语言模型分解为多个部分来实现推理加速。这些部分可以是在不同设备上执行的,例如在CPU、GPU或TPU上。通过这种方式,可以并行处理模型的不同部分,从而加快推理速度。 -
虚拟内存(Virtual Memory):vLLM推理框架利用虚拟内存技术来管理模型在内存中的数据。通过将模型所需的数据加载到虚拟内存中,可以减少实际内存的使用,并提高数据访问的速度。 -
量化(Quantization):vLLM推理框架通过将模型参数和输入数据从浮点数转换为低精度表示(如8位整数或4位整数)来实现推理加速。量化可以减少模型的参数量和计算量,从而加快推理速度。 -
蒸馏(Distillation):vLLM推理框架还可以通过蒸馏技术来减少模型的大小和计算复杂度。蒸馏是一种将大型教师模型(teacher model)的知识传递给小型学生模型(student model)的技术。学生模型具有较少的参数,但在性能上与教师模型相似。通过蒸馏,vLLM推理框架可以加速模型的推理速度。 -
混合精度(Mixed Precision):vLLM推理框架还可以使用混合精度技术,将模型中的某些部分保持为浮点数,而其他部分则使用低精度表示。这种方法可以在不牺牲太多性能的情况下,提高推理速度。 -
并行计算(Parallel Computing):vLLM推理框架可以利用并行计算技术来加速模型的推理。通过在多个处理器核心或多台设备上同时执行模型的一部分,可以显著提高推理速度。
因此现在越来越多基于vLLM部署的解决方案,极大的提升了原始基座模型的推理性能与并发性能。
结尾
后面会验证在vllm部署下的流式并发调用;模型的并行计算没有那么简单,Transformer模型并行计算的实现主要依赖于以下几种方法:
-
数据并行:这是最简单的并行方法,是将输入数据分割成多个部分,每个部分由不同的GPU处理。这种方法要求模型的输入和输出能够被分割,并且各个部分之间没有依赖关系。 -
模型并行:这种方法是将模型的不同部分放在不同的GPU上执行。例如,可以将Transformer模型的多个注意力头放在不同的GPU上计算,或者将编码器和解码器放在不同的GPU上。这种方法需要确保模型的各个部分能够独立工作,不会因共享内存而产生冲突。 -
流水线并行:这种方法是将模型的推理过程分成多个阶段,每个阶段可以在不同的GPU上执行。例如,第一个GPU可以负责前向传播,第二个GPU负责注意力层的计算,第三个GPU负责后向传播,以此类推。这种方法需要确保每个阶段的输出能够被下一个阶段正确接收。 -
混合并行:这是一种结合了上述多种并行方法的混合策略。例如,可以同时使用数据并行和模型并行,或者在同一个模型并行策略中结合流水线并行和模型并行。这种方法可以更灵活地利用可用的计算资源,但同时也增加了实现的复杂性。 -
参数服务器并行:这种方法是将模型的参数分布在多个服务器上,每个服务器负责存储和更新一部分参数。这种方法通常用于训练阶段,但在某些情况下也可以用于推理。
不过目前有对应的开源解决库,后面可以挖掘下其内在的知识点。
web_demo: https://github.com/THUDM/ChatGLM3/tree/main/basic_demo
[2]api_demo: https://github.com/THUDM/ChatGLM3/tree/main/openai_api_demo
[3]issue: https://github.com/THUDM/ChatGLM3/issues/1075
[4]使用指南-速率限制指南: https://open.bigmodel.cn/dev/howuse/rate-limits/level
[5]mosec部署chatglm2-6B: https://blog.csdn.net/aizaiyishunjian/article/details/132087614
[6]issue: https://github.com/hiyouga/LLaMA-Factory/issues/3118
原文始发于微信公众号(阿郎小哥的随笔驿站):聊聊ChatGLM3多用户并发API调用的问题
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/268725.html