目录
7、准备 Stable Diffusion 的 sd-svc 镜像
8、制作用于加速启动的 Bottlerocket snapshot
9、通过 Helm chart 安装 nvidia-k8s-plugin 插件
10、部署 Stable Difussion 的 sd-svc 服务
2、nvidia/k8s-device-plugin 带来的执行效率的讨论
随着 Stable Diffusion 等 AI 生图方案逐步普及,越来越多的场景被开发和落地。其中面向游戏 C 端玩家的 AI 生图营销活动场景正在被逐步验证:在某个游戏社区中,玩家一键从手机上传一张照片,AI 会将自动识别该照片中的元素并替换成游戏中相应的角色或物品,替换后的照片可以进一步被玩家传播,进而扩大活动影响力。这样的活动已经被应用于游戏新版本发布、展会等场景,能有效提升玩家与游戏之间的粘性,让玩家成为游戏的推广大使,为游戏拉新。
本文将根据企业级客户实际案例经验,探讨如何高效地办好这么一场游戏 AI 生图活动,并提出我们的解决方案,我们总结了以下要点:
- 包含了游戏风格与素材的 AI 模型,并调试出相应的推理算法。
- 有效触达游戏玩家的客户端,可以是游戏客户端本身,也可以是社交媒体,比如常见的游戏玩家聚集地,海外有 Discord,国内有 Fanbook、微信等。本方案选用 Discord 作为我们演示的客户端。
- 一套能快速伸缩承载高并发出图请求的后端架构:本方案选用 EKS,搭载了 EFS、Bottlerocket、GPU 时间分片虚拟化和 Karpenter 等组件作为演示的后端架构。
一、方案架构
方案上大致可以划分两大部份:
客户端和请求接入层:
首先我们选择 Discord 作为我们的客户端。Discord 是一款集语音、视频以及文字聊天于一体的服务软件。最早服务于电子游戏社区,但现在也用于 AI、Web 3.0、艺术、音乐等领域。用户可以在 Discord 上创建和加入各种类型的服务器,与其他用户进行实时的聊天和交流。Discord 服务器是 Discord 的核心功能,每个服务器里还能有自己的频道,用户可以在频道内与其他用户进行实时的文字、语音和视频聊天。在我们的场景里面,游戏玩家正是通过这些频道发起生图请求,并通过 Discord 服务器传递到接入层中。
接入层实现了一个 Discord bot,该 bot 包含两部分功能:1,更新 command,command 是用于引导游戏玩家便捷输入照片和提示词,并获得相应的输出照片。2,对来自游戏玩家的请求做筛选过滤和初步处理,在 3 秒钟之内(Discord 协议规定)做出初步响应,同时把符合条件需要生图的请求转发给 SQS。
接入层的 Discord bot 的实现参考了 Amazon Blog:An elastic deployment of Stable Diffusion with Discord on AWS,采用的是 API Gateway + Lambda 的 Serverless 架构,该架构提供了事件驱动型计算服务,使用者无需预置服务器便可快速构建自动扩展的程序。Discord bot 是 SQS 消息队列的生产端,通过 SQS 来实现与后端 AI 推理层的解耦。
后端 AI 推理集群:
SQS 的消费端是基于 EKS 构建起来后端 AI 推理集群。
首先,是一个 controller 模块,它会从 SQS 消费来自游戏玩家的消息以及相应的消息回调接口,之后按频道把消息分发到不同的 Stable Diffusion(SD)生图服务中,等待生图完成后,会再把生成的图片等结果发送到指定的消息回调接口,至此,一条游戏玩家生图请求就算最终完成了。
其次,是 sd-svc 服务,每一个服务托管了一种我们预设好的 Stable Diffusion 模型和算法组合,在本文后续部份,我们将会用 AUTOMATIC1111/stable-diffusion-webui 来托管我们的模型和算法。AUTOMATIC1111/stable-diffusion-webui 是一款当前流行的基于 Stable Diffusion 打造的工具应用,通过它可以方便进行文生图和图生图,并集成各种社区的插件,比如 LoRA 和 ControlNet 等。它自带 Web 界面,也同时支持 Web API 访问,本文中将使用 Web API 来访问。
在模型选择上,我们将选择一个已经事先训练好的包含魔兽世界游戏素材的模型 rpg_V4.safetensors,以及一个 ControlNet Canny 模型 control_v11p_sd15_canny 做为演示。在实际项目中,您还可以根据实际的游戏,利用该游戏素材,训练出具备该游戏特色的模型(关于 Stable Diffusion 模型训练,不是本文重点,如果感兴趣,可以参考如 Hugging Face 的训练一个 diffusion 模型文档)。
在面向 C 端游戏玩家的场景,如何在满足高并发的服务的同时,也兼顾成本效益,这是绕不开的话题,为此我们做了以下优化:
- bottlerocket-images-cache + 高性能 EBS:实现快速集群扩容。一般的扩容过程是:请求新增 Node → 启动并初始化 Node → 启动 Pod → 拉取 Container 镜像 → 启动进程初始化 → 开始提供服务,由于 Stable Diffusion 用到的 pytorch 框架以及相应依赖的工具包还有模型十分巨大,一个包含这些完整工具链 + 模型的镜像往往会达到 10G 以上,再加上 Stable Diffusion webUI 本身在第一次启动还有初始化过程,会导致集群扩容过程缓慢,一次扩容往往会达到 10 分钟以上。这样的扩容速度在面向 C 端场景里面,会显得比较滞后。我们的做法是:提前预设好优化过的容器镜像,并通过 bottlerocket-image-cache 把镜像制作成 snapshot,做为 volumn 被 Node 在启动时挂载,同时适当提升该 volumn 的 IO 吞吐,从而节省了大量的启动和初始化时间。在我们的实验环境里,总共 13GB(运行环境 78G + 2G 的 Checkpoint 模型文件 + 1.3G 的 ControlNet 模型文件)的镜像在优化之后,搭配 IO 吞吐为 500MB 的 GP3 EBS,从请求 Node 到可以开始提供服务(已加载 ckpt 模型)一共花了 1:40 分钟。
- EFS:实现模型文件一份存储和被动态加载。所有 pod 都可以通过挂载同一个 EFS 文件系统,实现动态加载模型的效果,运维人员只需要维护一份模型文件即可。同时 EFS 优秀的 IO 吞吐(Gbit/s 级别)也保障模型加载的速度。
- GPU 分片:提升 GPU 使用率,降低成本。如果您选用的 GPU 卡性能很强劲,而且 AI 推理的任务比较简单,无法占满该 GPU 卡,那么可以考虑让多个推理任务同时复用一张 GPU 卡来提升 GPU 卡的使用率。利用 NVIDIA/k8s-device-plugin 的时间分片能力可以很方便的管理 GPU 的算力。在我们的实验环境中,我们把一张型号为 A10g 的显卡切分为 3 个分片,每个分片各跑一个 pod,在推理任务接连不断满负荷的情况下,GPU 的利用率可以提升 9%(相同工作量的任务,总完成时间减少 11.9%)。
- Karpenter + Spot:更高的集群利用率加上更好的成本方案,进一步优化成本。
二、生图活动-端到端体验
打开 Discord 客户端,切换到已经绑定了 Discord bot 的频道中,在输入框输入“/”,会出/img2img 的提示词,按照指引选择一张照片,prompt 是可选的,能在前面 image 的基础上做最终效果调整,不加 prompt 举例:
加了 prompt “dog, Akita type” 举例,把一只猫微调为一只狗,增加可玩性,您也可以加入更多调节的选项给玩家提升高级玩家体验。
三、前置条件
本博客假设您已熟悉 Terraform、Docker、Discord、Amazon EC2、Amazon Elastic Block Store(Amazon EBS)、Amazon Virtual Private Cloud(Amazon VPC)、AWS Identity and Access Management(IAM)、Amazon API Gateway、AWS Lambda、Amazon SQS,Amazon Elastic Container Registry(Amazon ECR)、Elastic Kubernetes Service(EKS)、AWS Elastic File System(Amazon EFS)、Helm。
为了走通以下实验部份,您需要:
- 一个调试部署环境,该环境需要能运行 terraform、aws cli、docke,kubectl、eksctl、jq 命令,同时需要访问互联网。建议您选用基于 X86 架构的 AWS Cloud9 作为调试部署环境。
- 一个 AWS IAM 用户或者角色,具备开通部署 AWS service 的权限。
- 一个 discord 应用,您可以参考 Discord Document 来创建一个 Discord 应用,并加入您用来测试的 channel。创建完成后,您需要记录下:
- Discord Bot token (Bot → Reset Token)
- Discord Application ID(General Information → APPLICATION ID)
- Discord Public Key(General Information → PUBLIC KEY)
- EC2 的 Quota Limit:本次实验至少会用到 2xlarge * 1 和 m5.large * 2,如您不确定是否 limit 足够,建议按照该指引检查下。
四、方案走读
1、下载实验代码:
# Download lab repository
git clone https://github.com/aws-samples/gai-game