在云中高效实现模型服务
项目描述
在云中高效实现模型服务。
介绍
Mosec是一个高性能且灵活的模型服务框架,用于构建具有ML模型功能的后端和微服务。它将您刚刚训练的任何机器学习模型与高效的在线服务API之间的差距弥合。
- 高性能:使用Rust 🦀构建的Web层和任务协调,除了异步I/O带来的高效CPU利用率外,还提供了闪电般的速度
- 易用性:用户界面完全采用 Python 🐍 编写,用户可以使用与离线测试相同的代码以框架无关的方式在其模型中提供服务
- 动态批处理:聚合来自不同用户的批量推理请求并分發结果
- 管道化阶段:为管道化阶段启动多个进程以处理 CPU/GPU/IO 混合工作负载
- 云友好:设计用于在云中运行,具有模型预热、优雅关闭和 Prometheus 监控指标,可由 Kubernetes 或任何容器编排系统轻松管理
- 做好一件事:专注于在线服务部分,用户可以关注模型优化和业务逻辑
安装
Mosec 需要 Python 3.7 或更高版本。使用以下命令安装 Linux x86_64 或 macOS x86_64/ARM64 的最新 PyPI 软件包
pip install -U mosec
# or install with conda
conda install conda-forge::mosec
要从源代码构建,请安装 Rust 并运行以下命令
make package
您将在 dist
文件夹中获得一个 mosec 轮文件
用法
我们展示了 Mosec 如何帮助您轻松地将预训练的稳定扩散模型作为服务托管。您需要安装 diffusers 和 transformers 作为先决条件
pip install --upgrade diffusers[torch] transformers
编写服务器
点击此处获取带有说明的服务器代码。
首先,我们导入库并设置一个基本日志记录器以更好地观察发生的情况。
from io import BytesIO
from typing import List
import torch # type: ignore
from diffusers import StableDiffusionPipeline # type: ignore
from mosec import Server, Worker, get_logger
from mosec.mixin import MsgpackMixin
logger = get_logger()
然后,我们使用 3 个步骤构建一个 API,客户端可以查询文本提示并根据 稳定扩散 v1-5 模型 获取图像。
-
将您的服务定义为继承
mosec.Worker
的类。我们在这里还继承了MsgpackMixin
以使用 msgpack 序列化格式(a)。 -
在
__init__
方法中,初始化您的模型并将其放置到相应的设备上。可选地,您可以将self.example
分配给一些数据以预热(b) 模型。请注意,数据应与您的处理程序的输入格式兼容,我们将在下面详细说明。 -
重写
forward
方法以编写您的服务处理程序(c),签名forward(self, data: Any | List[Any]) -> Any | List[Any]
。接收/返回单个项目或元组取决于是否配置了 动态批处理(d)。
class StableDiffusion(MsgpackMixin, Worker):
def __init__(self):
self.pipe = StableDiffusionPipeline.from_pretrained(
"sd-legacy/stable-diffusion-v1-5", torch_dtype=torch.float16
)
self.pipe.enable_model_cpu_offload()
self.example = ["useless example prompt"] * 4 # warmup (batch_size=4)
def forward(self, data: List[str]) -> List[memoryview]:
logger.debug("generate images for %s", data)
res = self.pipe(data)
logger.debug("NSFW: %s", res[1])
images = []
for img in res[0]:
dummy_file = BytesIO()
img.save(dummy_file, format="JPEG")
images.append(dummy_file.getbuffer())
return images
[!NOTE]
(a) 在此示例中,我们以二进制格式返回图像,JSON 不支持(除非使用 base64 编码,这会使有效载荷更大)。因此,msgpack 更适合我们的需求。如果我们没有继承
MsgpackMixin
,则默认使用 JSON。换句话说,服务请求/响应的协议可以是 msgpack、JSON 或任何其他格式(请参阅我们的 混合)。(b) 预热通常有助于提前分配 GPU 内存。如果指定了预热示例,则服务将在示例通过处理程序转发后才能就绪。但是,如果没有给出示例,则第一个请求的延迟可能会更长。《example》应根据
forward
需要接收的内容设置为一个项目或元组。此外,如果您想使用多个不同的示例进行预热,可以设置multi_examples
(示例 在此处)。(c) 此示例显示了一个单阶段服务,其中
StableDiffusion
工作直接接收客户端的提示请求并返回图像。因此,可以将forward
视为一个完整的服务处理程序。但是,我们也可以设计一个多阶段服务,其中工作在管道中进行不同的工作(例如,下载图像、模型推理、后处理)。在这种情况下,整个管道被视为服务处理程序,第一个工作接收请求,最后一个工作发送响应。工作之间的数据流是通过进程间通信完成的。(d)由于在本示例中启用了动态批处理,因此
forward
方法将期望接收到一个字符串列表,例如,['一只可爱的猫在玩一个红色的球', '一个男人坐在电脑前', ...]
,这些字符串来自不同的客户端,用于批推理,从而提高系统吞吐量。
最后,我们将工作线程添加到服务器以构建一个单阶段工作流程(可以通过管道进一步提高吞吐量,请参阅此示例),并指定我们想要并行运行的进程数(num=1
),以及最大批处理大小(max_batch_size=4
,动态批处理在超时前可以累积的最大请求数量;超时由max_wait_time=10
(毫秒)定义,这意味着Mosec等待将批处理发送到工作线程的最长时间)。
if __name__ == "__main__":
server = Server()
# 1) `num` specifies the number of processes that will be spawned to run in parallel.
# 2) By configuring the `max_batch_size` with the value > 1, the input data in your
# `forward` function will be a list (batch); otherwise, it's a single item.
server.append_worker(StableDiffusion, num=1, max_batch_size=4, max_wait_time=10)
server.run()
运行服务器
点击我查看如何运行和查询服务器。
上述代码段已合并到我们的示例文件中。您可以直接在项目根目录下运行。我们首先查看命令行参数(解释在此)
python examples/stable_diffusion/server.py --help
然后以调试日志启动服务器
python examples/stable_diffusion/server.py --log-level debug --timeout 30000
在您的浏览器中打开http://127.0.0.1:8000/openapi/swagger/
以获取OpenAPI文档。
然后在另一个终端中测试它
python examples/stable_diffusion/client.py --prompt "a cute cat playing with a red ball" --output cat.jpg --port 8000
您将在当前目录下获得一个名为"cat.jpg"的图像。
您可以检查指标
curl http://127.0.0.1:8000/metrics
就是这样!您刚刚将您的stable-diffusion模型作为服务托管!😉
示例
更多现成的示例可以在示例部分找到。包括
- Pipeline:一个没有任何ML模型的无聊的echo演示。
- 请求验证:使用类型注解验证请求。
- 多路由:在一个服务中提供多个模型。
- 嵌入服务:与OpenAI兼容的嵌入服务。
- 重排服务:根据查询重排一系列段落。
- 共享内存IPC:使用共享内存进行进程间通信。
- 自定义GPU分配:部署多个副本,每个副本使用不同的GPU。
- 自定义指标:记录您自己的指标以进行监控。
- Jax即时编译推理:即时编译加快推理速度。
- PyTorch深度学习模型
配置
- 动态批处理
- 在调用
append_worker
时配置max_batch_size
和max_wait_time (毫秒)
。 - 确保使用
max_batch_size
值进行推理不会导致GPU内存溢出。 - 通常,
max_wait_time
应小于批推理时间。 - 如果启用,则当累积的请求数量达到
max_batch_size
或max_wait_time
已过时,将收集一个批处理。当流量高时,服务将受益于此功能。
- 在调用
- 有关其他配置,请参阅参数文档。
部署
- 如果您正在寻找安装了
mosec
的GPU基础镜像,您可以在官方镜像mosecorg/mosec
中进行检查。对于复杂用例,请查看envd。 - 此服务不需要Gunicorn或NGINX,但在必要时您当然可以使用ingress控制器。
- 由于它控制多个进程,因此此服务应该是容器中的PID 1进程。如果您需要在容器中运行多个进程,您需要一个监督器。您可以选择Supervisor或Horust。
- 请记住收集指标。
mosec_service_batch_size_bucket
显示批处理大小分布。mosec_service_batch_duration_second_bucket
显示每个阶段的每个连接的动态批处理持续时间(从接收第一个任务开始)。mosec_service_process_duration_second_bucket
显示每个阶段的每个连接的处理持续时间(包括IPC时间,但不包括mosec_service_batch_duration_second_bucket
)。mosec_service_remaining_task
显示当前正在处理的任务数量。mosec_service_throughput
显示服务吞吐量。
- 由于它具有优雅的关闭逻辑,请使用
SIGINT
(CTRL+C
)或SIGTERM
(kill {PID}
)停止服务。
性能调整
- 找出您的推理服务的最佳
max_batch_size
和max_wait_time
。指标将显示实际批处理大小和批处理持续时间的直方图。这些是调整这两个参数的关键信息。 - 尝试将整个推理过程分成单独的CPU和GPU阶段(参考DistilBERT)。不同阶段将在数据管道中运行,这将保持GPU忙碌。
- 您还可以调整每个阶段的工人数。例如,如果您的管道由预处理CPU阶段和模型推理GPU阶段组成,增加CPU阶段工人数可以帮助生成更多数据以在GPU阶段进行模型推理;增加GPU阶段工人数可以充分利用GPU内存和计算能力。这两种方式都可能有助于提高GPU利用率,从而提高服务吞吐量。
- 对于多阶段服务,请注意,通过不同阶段的数据将通过
serialize_ipc/deserialize_ipc
方法进行序列化/反序列化,因此可能非常大的数据可能会使整个管道变慢。默认情况下,序列化数据通过rust传递到下一个阶段,您可以选择启用共享内存以潜在地减少延迟(参考RedisShmIPCMixin)。 - 您应该选择合适的
serialize/deserialize
方法,这些方法用于解码用户请求和编码响应。默认情况下,两者都使用JSON。但是,JSON不支持图像和嵌入。您可以选择msgpack,它更快且二进制兼容(参考Stable Diffusion)。 - 配置OpenBLAS或MKL的线程。它可能无法选择当前Python进程使用的最合适的CPU。您可以通过使用env(参考自定义GPU分配)为每个工作者进行配置。
- 从客户端启用HTTP/2。自v0.8.8以来,
mosec
自动适应用户的协议(例如,HTTP/2)。
采用者
以下是一些使用Mosec的公司和个人用户
- Modelz:ML推理的无服务器平台。
- MOSS:类似于ChatGPT的开源对话语言模型。
- TencentCloud:腾讯云机器学习平台,使用Mosec作为核心推理服务器框架。
- TensorChord:云原生AI基础设施公司。
引用
如果您发现此软件对您的科研工作有帮助,请考虑引用
@software{yang2021mosec,
title = {{MOSEC: Model Serving made Efficient in the Cloud}},
author = {Yang, Keming and Liu, Zichen and Cheng, Philip},
url = {https://github.com/mosecorg/mosec},
year = {2021}
}
贡献
我们欢迎任何形式的贡献。请通过提出问题或在Discord上讨论来给我们反馈。您也可以直接贡献您的代码和pull请求!
要开始开发,您可以使用envd创建一个隔离和干净的Python & Rust环境。查看envd文档或build.envd获取更多信息。
项目详情
mosec-0.8.8.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 5047b6e7f0abe64e458bf5c24378659b4fca1d3b0cb459fab0480a6555429161 |
|
MD5 | c2035e22c4f01e39f73595db51b8099c |
|
BLAKE2b-256 | 87aa9179da0625d6608776f9e6ab1da233c518895db67de747a1f9a6aa14dceb |
mosec-0.8.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | da860043fa7180e5ddc93c688da683adb92b10930819991b98536b11b4a43777 |
|
MD5 | 52d215152a6103fb368a36dff2945a65 |
|
BLAKE2b-256 | 2426b41f5483f0aa5f1071929043bdbe5fa5564bede8f5f655e33dfd0e0efffc |
mosec-0.8.8-cp313-cp313-macosx_11_0_arm64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 70ae2d3b33cb399ad9e0d1c6caaff4fca1b73610608d8f34ff27673c704ff0b1 |
|
MD5 | 73f6675784b1c5e89267bb284b292c1d |
|
BLAKE2b-256 | 8b859ae6a0da5c6a7aabfe62c7e58ba786c5b0dd92d7379b5655fed2f329ff0d |
mosec-0.8.8-cp313-cp313-macosx_10_13_x86_64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 2eda992e541687cf1eb05f54a3fd62ee44ad1e6f71724e9a3cc80f7d9fb6239c |
|
MD5 | 45862439725d41b8bf6e030a36efebcb |
|
BLAKE2b-256 | f5cb615e1d1df42e52953cf695fae3c228881ff37d2fa1436507e4148efdbef2 |
mosec-0.8.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 1004a7e30c633e048a8cee81ce909f68a700884cee19094b804ce16dd1e11f5e |
|
MD5 | a91d244fe93dc0967e5c56225106e6e1 |
|
BLAKE2b-256 | a38fc0a15bbcb880987a156316c9b2df5f03ed47b4c8c8d385321d22825bb17c |
mosec-0.8.8-cp312-cp312-macosx_11_0_arm64.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 83268a168fea8519ff914842b3f05da3fcc0089cd37c34608cf8d176abcf326f |
|
MD5 | 7c3240346e91671c1feb91406c4b9bf2 |
|
BLAKE2b-256 | 5d0bca614562e10e97bb9da7b0635340a47c217817d33dc26870556ef5a31487 |
哈希值 用于 mosec-0.8.8-cp312-cp312-macosx_10_13_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 9c478034d4808c7a301b61b295606f0e2b923852e014811f653a18bea6e9e5c0 |
|
MD5 | cdbd10bab7bea4843b0d3c29efc9b393 |
|
BLAKE2b-256 | 28b59060859b912441945577951bb6f4a6b70a2916336be96b50f79c9a1bca03 |
哈希值 用于 mosec-0.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6d0ac34e978734f8a0c83f07e9752c7be827dcd84093bc159e500d39f4a8b559 |
|
MD5 | 045919cc84d4d611767fe7c173bfa029 |
|
BLAKE2b-256 | be5bda4ce77c2d43d480ca2ff3321b5ee70b5e750cddeef68d6eae5072680dad |
哈希值 用于 mosec-0.8.8-cp311-cp311-macosx_11_0_arm64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | fdf949fdcd8f1dee745e8d61df805ce7556db425f55d9de51fe610b77b911685 |
|
MD5 | 88c09a5c2bbbcc8bcbecafd3da24a2f8 |
|
BLAKE2b-256 | 48109cddc185e1e9a10a74e8b02a199a6d1b47bfc88448b1a82bd0c70fd4a453 |
哈希值 用于 mosec-0.8.8-cp311-cp311-macosx_10_9_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | adcda1275a078afe5b43f2383581ecd23fcb8ddf4825a9e0bc84b1e46714f840 |
|
MD5 | c95cb145447d130ce6b8c29edfc0b9b8 |
|
BLAKE2b-256 | 0da9e1ccae029cef462a56cee0b5cae2d7bc8609221a2783fe32f5a7808e9ae5 |
哈希值 用于 mosec-0.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 93e92936ecc08668a8fdcc9a2059dc9894768ebb9a94fbdd0f7f60da16ebbe39 |
|
MD5 | 523d5113726c7856c3748f77c9f34e80 |
|
BLAKE2b-256 | bacc3f7ae70eb897b5bbcd42eeca35c18b7d24cbe75e7c7157092ae33a9daa78 |
哈希值 用于 mosec-0.8.8-cp310-cp310-macosx_11_0_arm64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 9565f2d5983b36f0f16705e0d34ec9355dd18653ffd96e0e8013174378240b15 |
|
MD5 | bf55b83d9b2a9146b8eacab172c69a0c |
|
BLAKE2b-256 | fa40911a42284cf3e45a4e79ee5df6c35a2c318f4f836c1972e7159f376f8186 |
哈希值 用于 mosec-0.8.8-cp310-cp310-macosx_10_9_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 84c4581d0c7e045c6c7894750324d7f6cd4a7d1af5ad2c5ff4fac8796435fc87 |
|
MD5 | edb9013be8bc02cab373ed8dee0a0e6e |
|
BLAKE2b-256 | 369593d4706b85f811da177329389f2eb12b2bfb60fba6405ba61662b4606663 |
哈希值 用于 mosec-0.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f3ebdb8038bf9a870f5270e63d5a371918a224333a17eb952c693c0a1f67f842 |
|
MD5 | b82be6a5557d57edf396c2acfc31831e |
|
BLAKE2b-256 | 3647e305389d7106baf2b3078243a6fdbb1a646f741bb923c8214f321e1d5c7a |
哈希值 用于 mosec-0.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f4fc851cf1470ac94484926abdd1ea24a99f2964662fb2a5801e72a88ec99706 |
|
MD5 | f156e25cf49dc892952c6f987f03c108 |
|
BLAKE2b-256 | 6b547e46b0f7a2cfb30724c5cbc770dcb19862cbd9a6815138965ad64df3653e |