最新消息
- [2024/01] DeepSpeed-FastGen:引入Mixtral、Phi-2和Falcon支持,具备重要的性能和功能增强
- [2023/11] DeepSpeed-FastGen:通过MII和DeepSpeed-Inference实现LLMs的高吞吐量文本生成
- [2022/11] 使用DeepSpeed MII在1秒内生成稳定扩散图像
- [2022/10] 宣布DeepSpeed模型推理实现 (MII)
目录
DeepSpeed模型推理实现 (MII)
介绍MII,这是由DeepSpeed设计的开源Python库,旨在普及强大的模型推理,重点在于高吞吐量、低延迟和成本效益。
- MII功能包括阻塞式KV缓存、连续批处理、动态SplitFuse、张量并行和高性能CUDA内核,以支持如Llama-2-70B、Mixtral (MoE) 8x7B和Phi-2等模型的快速高吞吐量文本生成。最新的v0.2更新增加了新的模型系列、性能优化和功能增强。MII现在提供了比领先系统如vLLM高达2.5倍的有效吞吐量。有关详细的性能结果,请参阅我们的最新DeepSpeed-FastGen博客和DeepSpeed-FastGen发布博客。
- 我们在2022年首次宣布MII,涵盖了所有之前的发布版本至v0.0.9。除了语言模型外,我们还支持加速如稳定扩散的text2image模型。有关我们先前发布的详细信息,请参阅我们的旧版API。
关键技术
MII用于高吞吐量文本生成
MII通过使用四项关键技术提供加速文本生成推理:
- 阻塞式KV缓存
- 连续批处理
- 动态SplitFuse
- 高性能CUDA内核
要深入了解这些功能,请参考我们的博客,其中还包括详细的性能分析。
MII旧版
过去,MII介绍了几项用于低延迟服务场景的关键性能优化:
- 变压器的DeepFusion
- 使用张量切片的多GPU推理
- 资源受限系统的ZeRO推理
- 编译器优化
MII如何工作?
图1:MII架构,展示了MII如何在部署之前自动使用DS-Inference优化开源模型。图中的DeepSpeed-FastGen优化已在我们的博客文章中发布。
MII的底层由DeepSpeed-Inference提供支持。根据模型架构、模型大小、批处理大小和可用硬件资源,MII会自动应用适当的一系列系统优化,以最小化延迟并最大化吞吐量。
支持的模型
MII目前支持超过37000种模型,涵盖八种流行的模型架构。我们计划在短期内增加更多模型,如果您希望支持特定的模型架构,请提交问题并告知我们。所有当前模型都利用后端的Hugging Face来提供模型权重和相应的分词器。对于我们当前的发布版本,我们支持以下模型架构:
模型系列 | 大小范围 | 大约模型数量 |
---|---|---|
falcon | 7B - 180B | 500 |
llama | 7B - 65B | 52000 |
llama-2 | 7B - 70B | 1200 |
mistral | 7B | 23000 |
mixtral (MoE) | 8x7B | 2900 |
opt | 0.1B - 66B | 2100 |
phi-2 | 2.7B | 1500 |
qwen | 7B - 72B | 500 |
MII旧版模型支持
MII旧版API支持超过50000种不同的模型,包括BERT、RoBERTa、稳定扩散和如Bloom、GPT-J等文本生成模型。完整列表请参见我们的旧版支持模型表。
MII的入门指南
DeepSpeed-MII允许用户仅用几行代码创建支持模型的非持久和持久部署。
安装
最快的开始方式是使用我们的DeepSpeed-MII的PyPI发布版,这意味着你可以在几分钟内开始:
pip install deepspeed-mii
为了简化使用并显著减少在此领域项目通常需要的漫长编译时间,我们通过一个名为DeepSpeed-Kernels的新库分发了覆盖大多数自定义内核的预编译python轮子。我们发现这个库在具有计算能力8.0+ (Ampere+)、CUDA 11.6+和Ubuntu 20+的NVIDIA GPU环境中非常容易移植。在大多数情况下,你甚至不需要知道这个库的存在,因为它是DeepSpeed-MII的依赖项,会随它一起安装。然而,如果由于某种原因你需要手动编译我们的内核,请参阅我们的高级安装文档。
非持久管道
非持久管道是尝试DeepSpeed-MII的好方法。非持久管道仅在你运行的python脚本期间存在。运行非持久管道部署的完整示例只有4行代码。试试看!
import mii
pipe = mii.pipeline("mistralai/Mistral-7B-v0.1")
response = pipe(["DeepSpeed is", "Seattle is"], max_new_tokens=128)
print(response)
返回的response
是一个Response
对象列表。我们可以访问有关生成的多个细节(例如,response[0].prompt_length
):
generated_text: str
模型生成的文本。prompt_length: int
原始提示的令牌数量。generated_length: int
生成的令牌数量。finish_reason: str
停止生成的原因。stop
表示生成了EOS令牌,length
表示生成达到了max_new_tokens
或max_length
。
如果你想释放设备内存并销毁管道,请使用destroy
方法:
pipe.destroy()
张量并行
利用多GPU系统来获得更高性能在MII中很容易。当使用deepspeed
启动器运行时,张量并行由--num_gpus
标志自动控制:
# 在单个GPU上运行
deepspeed --num_gpus 1 mii-example.py
# 在多个GPU上运行
deepspeed --num_gpus 2 mii-example.py
管道选项
虽然仅需要模型名称或路径即可建立非持久管道部署,但我们为用户提供了自定义选项:
mii.pipeline()
选项:
model_name_or_path: str
HuggingFace模型的名称或本地路径。max_length: int
设置提示+响应的默认最大令牌长度。all_rank_output: bool
启用时,所有等级返回生成的文本。默认情况下,只有等级0返回文本。
用户还可以使用以下选项控制个别提示的生成特性(即调用pipe()
时):
max_length: int
设置每个提示的提示+响应的最大令牌长度。min_new_tokens: int
设置响应中生成的最小令牌数量。max_length
将优先于此设置。max_new_tokens: int
设置响应中生成的最大令牌数量。ignore_eos: bool
(默认值为False
)设置为True
时,防止在遇到EOS令牌时结束生成。top_p: float
(默认值为0.9
)当设置为小于1.0
时,过滤令牌并仅保留最可能的令牌,其令牌概率和≥top_p
。top_k: int
(默认值为None
)当为None
时,禁用top-k过滤。当设置时,保留最高概率的令牌数量。temperature: float
(默认值为None
)当为None
时,禁用温度设置。当设置时,调节令牌概率。do_sample: bool
(默认值为True
)当为True
时,采样输出对数。当为False
时,使用贪婪采样。return_full_text: bool
(默认值为False
)当为True
时,将输入提示前置到返回文本中
持久部署
持久部署非常适用于长时间运行和生产应用。持久模型使用轻量级GRPC服务器,可以同时被多个客户端查询。运行持久模型的完整示例只有5行代码。试试看!
import mii
client = mii.serve("mistralai/Mistral-7B-v0.1")
response = client.generate(["Deepspeed is", "Seattle is"], max_new_tokens=128)
print(response)
返回的response
是一个Response
对象列表。我们可以访问有关生成的多个细节(例如,response[0].prompt_length
):
generated_text: str
模型生成的文本。prompt_length: int
原始提示的令牌数量。generated_length: int
生成的令牌数量。finish_reason: str
停止生成的原因。stop
表示生成了EOS令牌,length
表示生成达到了max_new_tokens
或max_length
。
如果我们想从其他进程生成文本,也可以:
client = mii.client("mistralai/Mistral-7B-v0.1")
response = client.generate("Deepspeed is", max_new_tokens=128)
当我们不再需要持久部署时,可以从任何客户端关闭服务器:
client.terminate_server()
模型并行
利用多GPU系统以获得更好的延迟和吞吐量在持久部署中也很简单。模型并行由mii.serve
的tensor_parallel
输入控制:
client = mii.serve("mistralai/Mistral-7B-v0.1", tensor_parallel=2)
结果部署将模型分布在2个GPU上,以提供比单个GPU更快的推理和更高的吞吐量。
模型复制
通过设置多个模型副本并利用DeepSpeed-MII提供的负载平衡,我们还可以利用多GPU(和多节点)系统:
client = mii.serve("mistralai/Mistral-7B-v0.1", replica_num=2)
结果部署将加载2个模型副本(每个GPU一个)并在2个模型实例之间负载均衡传入请求。
模型并行和副本还可以结合使用,以利用具有更多GPU的系统。在下面的示例中,我们在一个有4个GPU的系统上运行2个模型副本,每个副本分布在2个GPU上:
client = mii.serve("mistralai/Mistral-7B-v0.1", tensor_parallel=2, replica_num=2)
选择模型并行或模型复制最大性能取决于硬件、模型和工作负载的性质。例如,对于小模型,用户可能会发现模型复制提供了最低的请求平均延迟。与此同时,对于大模型,使用仅模型并行可能实现更大的总体吞吐量。
RESTful API
通过在创建持久MII部署时设置enable_restful_api=True
,MII可以轻松地通过RESTful API设置和运行模型推理。RESTful API可以在http://{HOST}:{RESTFUL_API_PORT}/mii/{DEPLOYMENT_NAME}
接收请求。完整示例如下:
client = mii.serve(
"mistralai/Mistral-7B-v0.1",
deployment_name="mistral-deployment",
enable_restful_api=True,
restful_api_port=28080,
)
📌 注意: 虽然提供deployment_name
不是必要的(MII会为你自动生成一个),但最好提供一个deployment_name
,以确保你与正确的RESTful API接口。
然后你可以使用任何HTTP客户端向RESTful网关发送提示,例如curl
:
curl --header "Content-Type: application/json" --request POST -d '{"prompts": ["DeepSpeed is", "Seattle is"], "max_length": 128}' http://localhost:28080/mii/mistral-deployment
或者python
:
import json
import requests
url = f"http://localhost:28080/mii/mistral-deployment"
params = {"prompts": ["DeepSpeed is", "Seattle is"], "max_length": 128}
json_params = json.dumps(params)
output = requests.post(
url, data=json_params, headers={"Content-Type": "application/json"}
)
持久部署选项
虽然仅需模型名称或路径即可启动持久部署,我们为用户提供了自定义选项。
mii.serve()
选项:
model_name_or_path: str
(必需) HuggingFace 模型的名称或本地路径。max_length: int
(默认为模型配置中的最大序列长度) 设置提示和响应的默认最大令牌长度。deployment_name: str
(默认为f"{model_name_or_path}-mii-deployment"
) 持久模型的唯一识别字符串。如果提供,客户端对象应通过client = mii.client(deployment_name)
检索。tensor_parallel: int
(默认为1
) 拆分模型的GPU数量。replica_num: int
(默认为1
) 启动的模型副本数量。enable_restful_api: bool
(默认为False
) 启用后,将启动一个RESTful API网关进程,可以在http://{host}:{restful_api_port}/mii/{deployment_name}
进行查询。详情见 RESTful API 部分。restful_api_port: int
(默认为28080
) 在enable_restful_api
为True
时,用于接口RESTful API的端口号。
mii.client()
选项:
model_or_deployment_name: str
传递给mii.serve()
的模型或deployment_name
的名称。
用户还可以通过以下选项控制单个提示的生成特性(即调用client.generate()
):
max_length: int
设置每个提示的最大令牌长度(包括提示和响应)。min_new_tokens: int
设置响应中生成的最少令牌数。在此设置中,max_length
将优先。max_new_tokens: int
设置响应中生成的最大令牌数。ignore_eos: bool
(默认为False
) 设为True
时,遇到EOS令牌时将不会结束生成。top_p: float
(默认为0.9
) 设置为低于1.0
时,过滤令牌,并仅保留最可能的令牌,其中令牌概率和≥top_p
。top_k: int
(默认为None
) 设置为None
时,禁用top-k过滤。设置时,保留最高概率的令牌数量。temperature: float
(默认为None
) 设置为None
时,禁用温度。设置时,会调节令牌概率。do_sample: bool
(默认为True
) 设为True
时,进行输出logit采样。设为False
时,使用贪婪采样。return_full_text: bool
(默认为False
) 设为True
时,将输入提示附加到返回文本。
贡献
本项目欢迎贡献和建议。大多数贡献需要你同意一份贡献者许可协议 (CLA),声明你有权且实际授予我们使用你的贡献的权利。详情见 https://cla.opensource.microsoft.com。
当你提交拉取请求时,CLA 机器人会自动确定你是否需要提供 CLA 并适当地装饰 PR (例如,状态检查、评论)。请只需按照机器人提供的说明操作。你只需在所有使用我们CLA的仓库中做一次。
本项目采纳了微软开源行为准则。更多信息请访问 行为准则常见问题或联系 opencode@microsoft.com 提出任何其他问题或意见。
商标
本项目可能包含项目、产品或服务的商标或徽标。使用微软商标或徽标需遵守并必须遵循微软商标和品牌指南。在本项目修改版本中使用微软商标或徽标不得引起混淆或暗示微软赞助。使用第三方商标或徽标需遵守这些第三方的政策。