跳转到主要内容

在云中高效实现模型服务

项目描述

MOSEC

discord invitation link PyPI version conda-forge Python Version PyPi monthly Downloads License Check status

在云中高效实现模型服务。

介绍

MOSEC

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 如何帮助您轻松地将预训练的稳定扩散模型作为服务托管。您需要安装 diffuserstransformers 作为先决条件

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 模型 获取图像。

  1. 将您的服务定义为继承 mosec.Worker 的类。我们在这里还继承了 MsgpackMixin 以使用 msgpack 序列化格式(a)

  2. __init__ 方法中,初始化您的模型并将其放置到相应的设备上。可选地,您可以将 self.example 分配给一些数据以预热(b) 模型。请注意,数据应与您的处理程序的输入格式兼容,我们将在下面详细说明。

  3. 重写 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模型作为服务托管!😉

示例

更多现成的示例可以在示例部分找到。包括

配置

  • 动态批处理
    • 在调用append_worker时配置max_batch_sizemax_wait_time (毫秒)
    • 确保使用max_batch_size值进行推理不会导致GPU内存溢出。
    • 通常,max_wait_time应小于批推理时间。
    • 如果启用,则当累积的请求数量达到max_batch_sizemax_wait_time已过时,将收集一个批处理。当流量高时,服务将受益于此功能。
  • 有关其他配置,请参阅参数文档

部署

  • 如果您正在寻找安装了mosec的GPU基础镜像,您可以在官方镜像mosecorg/mosec中进行检查。对于复杂用例,请查看envd
  • 此服务不需要Gunicorn或NGINX,但在必要时您当然可以使用ingress控制器。
  • 由于它控制多个进程,因此此服务应该是容器中的PID 1进程。如果您需要在容器中运行多个进程,您需要一个监督器。您可以选择SupervisorHorust
  • 请记住收集指标
    • 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显示服务吞吐量。
  • 由于它具有优雅的关闭逻辑,请使用SIGINTCTRL+C)或SIGTERMkill {PID})停止服务。

性能调整

  • 找出您的推理服务的最佳max_batch_sizemax_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的公司和个人用户

引用

如果您发现此软件对您的科研工作有帮助,请考虑引用

@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获取更多信息。

项目详情


发布历史 发布通知 | RSS源

下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

mosec-0.8.8.tar.gz (86.8 kB 查看哈希值)

上传时间

构建分发

mosec-0.8.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB 查看哈希值)

上传时间 CPython 3.13 manylinux: glibc 2.17+ x86-64

mosec-0.8.8-cp313-cp313-macosx_11_0_arm64.whl (4.9 MB 查看哈希值)

上传时间 CPython 3.13 macOS 11.0+ ARM64

mosec-0.8.8-cp313-cp313-macosx_10_13_x86_64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.13 macOS 10.13+ x86-64

mosec-0.8.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB 查看哈希值)

上传时间: CPython 3.12 manylinux: glibc 2.17+ x86-64

mosec-0.8.8-cp312-cp312-macosx_11_0_arm64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.12 macOS 11.0+ ARM64

mosec-0.8.8-cp312-cp312-macosx_10_13_x86_64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.12 macOS 10.13+ x86-64

mosec-0.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB 查看哈希值)

上传时间: CPython 3.11 manylinux: glibc 2.17+ x86-64

mosec-0.8.8-cp311-cp311-macosx_11_0_arm64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.11 macOS 11.0+ ARM64

mosec-0.8.8-cp311-cp311-macosx_10_9_x86_64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.11 macOS 10.9+ x86-64

mosec-0.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB 查看哈希值)

上传时间: CPython 3.10 manylinux: glibc 2.17+ x86-64

mosec-0.8.8-cp310-cp310-macosx_11_0_arm64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.10 macOS 11.0+ ARM64

mosec-0.8.8-cp310-cp310-macosx_10_9_x86_64.whl (4.9 MB 查看哈希值)

上传时间: CPython 3.10 macOS 10.9+ x86-64

mosec-0.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB 查看哈希值)

上传于 CPython 3.9 manylinux: glibc 2.17+ x86-64

mosec-0.8.8-cp39-cp39-macosx_11_0_arm64.whl (4.9 MB 查看哈希值)

上传于 CPython 3.9 macOS 11.0+ ARM64

mosec-0.8.8-cp39-cp39-macosx_10_9_x86_64.whl (4.9 MB 查看哈希值)

上传于 CPython 3.9 macOS 10.9+ x86-64

mosec-0.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB 查看哈希值)

上传于 CPython 3.8 manylinux: glibc 2.17+ x86-64

mosec-0.8.8-cp38-cp38-macosx_11_0_arm64.whl (4.9 MB 查看哈希值)

上传于 CPython 3.8 macOS 11.0+ ARM64

mosec-0.8.8-cp38-cp38-macosx_10_9_x86_64.whl (4.9 MB 查看哈希值)

上传于 CPython 3.8 macOS 10.9+ x86-64

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面