赞
踩
随着 3 月 15 日 OpenAI 重磅发布了 GPT4,其在司法考试、程序编程上的惊艳表现,将大家对大模型的热情推向了顶点,人们纷纷讨论是否我们已经进入到通用人工智能的时代。与此同时,基于大语言模型的应用也如雨后春笋出现在大家面前,其在协同办公、客服对话、语言翻译、内容生成等方面的使用均来带了前所未有的畅快体验。
在我们享受大语言模型带来的普惠 AI 能力时,它也给开发者带来了前所未有的挑战。GPT3 模型具有 1750 亿参数量,即使是针对学术界和初级用户的 Alpaca 也具有 70 亿的参数量,因此单机多卡的分布式推理便成为了大模型落地方案的不二选择。
本文将以 Bloom7B1 模型为样例,分享在阿里云容器服务 ACK 上,进行大语言模型分布式推理的具体实践。
随着越来越多的大语言模型发布,其中也有很多表现优秀的开源大语言模型能让大家体验,人们通过已有的大语言模型构建自己的应用也不再遥不可及。然而,与以往的模型不同,单张 GPU 卡的显存可能不足以支撑大语言模型。因此,需要使用模型并行技术,将大语言模型进行切分后,在多张 GPU 卡上进行推理。在本文中,我们使用 DeepSpeed Inference 来部署大语言模型分布式推理服务。
DeepSpeed Inference 是 Microsoft 提供的分布式推理解决方案,能够很好的支持 transformer 类型的大语言模型。DeepSpeed Inference 提供了模型并行能力,在多 GPU 上对大模型并行推理。通过张量并行技术同时利用多个 GPU,提高推理性能。DeepSpeed 还提供了优化过的推理定制内核来提高 GPU 资源利用率,降低推理延迟。详细信息可参考DeepSpeed Inference[3]。
有了大模型分布式推理方案,然而想要在 Kubernetes 集群中高效部署大模型推理服务,还存在很多工程化挑战,比如大规模的 GPU 等异构资源如何高效地管理运维和自动调度?如何快速部署推理服务,服务上线后如何保证资源能够应对波动的访问量?以及没有适合的工具进行推理服务时延、吞吐、GPU 利用率、显存占用等关键指标监控,没有合理的模型切分方案,模型版本管理等。
本文使用阿里云容器服务 ACK 云原生 AI 套件进行 DeepSpeed 分布式推理的实践,可以轻松管理大规模异构资源,精细化的 GPU 调度策略和丰富的 GPU 监控告警能力,使用 Arena 快速提交和管理可弹性伸缩的推理服务,以及服务化运维等。
本例中会使用以下组件:
下列示例中,我们通过 Arena 在 Kubernetes 集群中部署了基于 Bloom 7B1 模型的单机多卡分布式推理服务,使用 DJLServing 作为模型服务框架。DJLServing 是由 Deep Java Library (DJL) 提供支持的高性能通用模型服务解决方案,能直接支持 DeepSpeed Inference,通过 HTTP 提供大模型推理服务,详细信息可参考 DJLServing[4]。使用 Arena 提交推理任务,在 Kubernetes 中使用 Deployment 部署推理服务,从共享存储 OSS 中加载模型和配置文件,通过 Service 暴露服务,为推理服务提供弹性伸缩、GPU 共享调度、性能监控、成本分析与优化等功能,降低您的运维成本。
接下来演示如何使用 Arena 命令行工具,在 ACK 容器服务中提交一个 Bloom7B1 模型的单机多卡分布式推理任务,并配置 Ingress 来进行服务访问。
模型配置中包括了两个方面的内容:
serving.properties 内容如下:
- engine=DeepSpeed
- option.parallel_loading=true
- option.tensor_parallel_degree=2
- option.model_loading_timeout=600
- option.model_id=model/LLM/bloom-7b1/deepspeed/bloom-7b1
- option.data_type=fp16
- option.max_new_tokens=100
model.py 内容如下:
- mport os
- import torch
- from typing import Optional
-
- import deepspeed
- import logging
- logging.basicConfig(format='[%(asctime)s] %(filename)s %(funcName)s():%(lineno)i [%(levelname)s] %(message)s', level=logging.DEBUG)
- from djl_python.inputs import Input
- from djl_python.outputs import Output
- from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
-
- predictor = None
-
-
- def get_model(properties: dict):
- model_dir = properties.get("model_dir")
- model_id = properties.get("model_id")
- mp_size = int(properties.get("tensor_parallel_degree", "2"))
- local_rank = int(os.getenv('OMPI_COMM_WORLD_LOCAL_RANK', '0'))
- logging.info(f"process [{os.getpid()} rank is [{local_rank}]]")
- if not model_id:
- model_id = model_dir
- logging.info(f"rank[{local_rank}] start load model")
- model = AutoModelForCausalLM.from_pretrained(model_id)
- tokenizer = AutoTokenizer.from_pretrained(model_id)
- logging.info(f"rank[{local_rank}] success load model")
-
- model = deepspeed.init_inference(model,
- mp_size=mp_size,
- dtype=torch.float16,
- replace_method='auto',
- replace_with_kernel_inject=True)
- logging.info(f"rank[{local_rank}] success to convert model to deepspeed kernel")
-
- return pipeline(task='text-generation',
- model=model,
- tokenizer=tokenizer,
- device=local_rank)
-
-
- def handle(inputs: Input) -> Optional[Output]:
- global predictor
- if not predictor:
- predictor = get_model(inputs.get_properties())
-
- if inputs.is_empty():
- # Model server makes an empty call to warmup the model on startup
- return None
-
- data = inputs.get_as_string()
- output = Output()
- output.add_property("content-type", "application/json")
- result = predictor(data, do_sample=True, max_new_tokens=50)
- return output.add(result)
分别将 serving.properties、model.py 和模型文件(可选)上传到 OSS 上。具体操作,请参见控制台上传文件[7]。
上传到 OSS 之后,分别创建名称为 bloom7b1-pv 和 bloom7b1-pvc 的 PV 和 PVC,以用于推理服务的容器挂载。具体操作,请参见使用 OSS 静态存储卷[8]。
将配置文件信息放入 PVC 中,可通过下列 arena 命令启动推理服务。
- arena serve custom \
- --name=bloom7b1-deepspeed \
- --gpus=2 \
- --version=alpha \
- --replicas=1 \
- --restful-port=8080 \
- --data=bloom7b1-pvc:/model \
- --image=ai-studio-registry-vpc.cn-beijing.cr.aliyuncs.com/kube-ai/djl-serving:2023-05-19 \
- "djl-serving -m "
查看任务运行情况。
- $ kubectl get pod | grep bloom7b1-deepspeed-alpha-custom-serving
- bloom7b1-deepspeed-alpha-custom-serving-766467967d-j8l2l 1/1 Running 0 8s
-
- # 查看启动日志
- kubectl logs bloom7b1-deepspeed-alpha-custom-serving-766467967d-j8l2l -f
服务启动日志如下,通过日志我们可以看到:
- INFO ModelServer Starting model server ...
- INFO ModelServer Starting djl-serving: 0.23.0-SNAPSHOT ...
- INFO ModelServer
- INFO PyModel Loading model in MPI mode with TP: 2.
- INFO PyProcess [1,0]<stdout>:process [92 rank is [0]]
- INFO PyProcess [1,0]<stdout>:rank[0] start load model
- INFO PyProcess [1,1]<stdout>:process [93 rank is [1]]
- INFO PyProcess [1,1]<stdout>:rank[1] start load model
- INFO PyProcess [1,0]<stdout>:rank[0] success to convert model to deepspeed kernel
- INFO PyProcess [1,1]<stdout>:rank[1] success to convert model to deepspeed kernel
- INFO PyProcess [1,0]<stdout>:rank[0] success load model
- INFO PyProcess [1,1]<stdout>:rank[1] success load model
- INFO PyProcess Model [deepspeed] initialized.
- INFO PyProcess Model [deepspeed] initialized.
- INFO PyModel deepspeed model loaded in 297083 ms.
- INFO ModelServer Initialize BOTH server with: EpollServerSocketChannel.
- INFO ModelServer BOTH API bind to: http://0.0.0.0:8080
这里我们启动 port-forward 来进行快速验证
- # 使用 kubectl 启动port-forward
- kubectl -n default-group port-forward svc/bloom7b1-deepspeed-alpha 9090:8080
在另一个终端,请求服务
- # 打开新的终端,执行下列命令
- $ curl -X POST http://127.0.0.1:9090/predictions/deepspeed -H "Content-type: text/plain" -d "I'm very thirsty, I need"
- [
- {
- "generated_text":"I'm very thirsty, I need some water.\nWhat are you?\n- I'm a witch.\n- I thought you'd say that.\nI know a great witch.\nShe's right in here.\n- You know where we can go?\n- That's right, in one moment.\n- You want to"
- }
- ]
我们可配置 Ingress 来将模型服务对外透出,以用来对外部流量进行管理,保证模型可用性。为上面创建的服务配置 Ingress 流程如下:
更详细的 Ingress 配置策略可以参考:创建 Nginx Ingress[9]
填写如下信息
Ingress 创建成功后,可以 Ingress 配置的域名来对 Bloom 模型进行访问。
- % curl -X POST http://deepspeed-bloom7b1.c78d407e5fa034a5aa9ab10e577e75ae9.cn-beijing.alicontainer.com/predictions/deepspeed -H "Content-type: text/plain" -d "I'm very thirsty, I need"
- [
- {
- "generated_text":"I'm very thirsty, I need to drink!\nI want more water.\nWhere is the water?\nLet me have the water, let me have the water...\nWait!\nYou're the father aren't you?\nDo you have water?\nAre you going to let me have some?\nGive me the"
- }
- ]
通过上面的例子,我们展示了如何使用 Arena 部署了一个 Bloom7B1 模型的单机多卡推理服务,使用 DeepSpeed-Inference 的模型并行推理技术,在多张 GPU 上进行推理。除了 DeepSpeed-Inference,当前也有一些其他的大模型分布式推理方案,比如 FastTransformer + Triton。后续我们也将不断探索,希望能够通过云原生 AI 套件,结合大模型分布式推理方案,用更低的成本支持高性能、低延迟、可弹性伸缩的大模型推理服务。
相关链接:
[1] 云原生 AI 套件开发者使用指南
https://help.aliyun.com/document_detail/336968.html?spm=a2c4g.212117.0.0.14a47822tIePxy
[2] Ingress 概述
https://help.aliyun.com/document_detail/198892.html?spm=a2c4g.181477.0.0.67d5225chicJHP
[3] DeepSpeed Inference
https://www.deepspeed.ai/tutorials/inference-tutorial/
[4] DJLServing
https://github.com/deepjavalibrary/djl-serving
[5] 创建托管 GPU 集群
https://help.aliyun.com/document_detail/171074.html?spm=a2c4g.171073.0.0.4c78f95a00Mb5P
[6] 安装云原生 AI 套件
https://help.aliyun.com/document_detail/201997.html?spm=a2c4g.212117.0.0.115b1cb6yDEAjy
[7] 控制台上传 OSS 文件
[8] 使用 OSS 静态存储卷
https://help.aliyun.com/document_detail/134903.html?spm=a2c4g.134903.0.0.132a4e96wLxEPu
[9] 创建 Nginx ingress
https://help.aliyun.com/document_detail/86536.html?spm=a2c4g.198892.0.0.3acd663fsFwQPY
点击立即免费试用云产品 开启云上实践之旅!
本文为阿里云原创内容,未经允许不得转载。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。