0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

优化 Stable Diffusion 在 GKE 上的启动体验

谷歌开发者 来源:未知 2023-06-03 08:35 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

以下文章来源于谷歌云服务,作者 Google Cloud

背景


现如今随着 AIGC 这个话题越来越热,越来越多优秀的开源项目基于文生图的 AI 模型如 MidJourney,Stable Diffusion 等应运而生。Stable Diffusion 是一个文字生成图像的 Diffusion 模型,它能够根据给定任何文本输入生成逼真的图像。我们在 GitHub Repo 中提供了三种不同的解决方案 (可参考https://github.com/nonokangwei/Stable-Diffusion-on-GCP),可以快速地分别在 GCP Vertex AI,GKE,和基于 Agones 的平台上部署 Stable Diffusion,以提供弹性的基础设施保证 Stable Diffusion 提供稳定的服务。本文将重点讨论 Stable Diffusion 模型在 GKE 上的实践。


提出问题


在实践中,我们也遇到了一些问题,例如 Stable Diffusion 的容器镜像较大,大约达到 10-20GB,导致容器在启动过程中拉取镜像的速度变慢,从而影响了启动时间。在需要快速扩容的场景下,启动新的容器副本需要超过 10 分钟的时间,严重影响了用户体验。



我们看到容器的启动过程,按时序排列:

触发 Cluster Autoscaler 扩容 + Node 启动并调度 Pod: 225s

启动 Pull Image:4s

拉取镜像: 5m 23s

启动 Pod:1s

能够提供 sd-webui 的服务 (大约): > 2m


在这段时序分析中,我们可以看到,在 Stable Diffusion WebUI 运行在容器上启动慢主要面临的问题是由于整个 runtime 依赖较多,导致容器镜像太大从而花费了很长时间拉取下载、也造成了 pod 启动初始化加载时间过长。于是,我们考虑优化启动时间从以下三个方面入手:

优化 Dockerfile,选择正确的 base image,精简 runtime 的依赖安装,减小镜像大小。

借助基础环境与 runtime 依赖分离方式,通过磁盘复制方式加速运行环境的创建。

通过 GKE Image Streaming 优化镜像加载时间,利用 Cluster Autoscaler 提升弹性扩缩容速度。


本文着重为大家介绍通过基础环境与 runtime 依赖分离方式,借助磁盘复制的高性能来优化 Stable Diffusion WebUI 容器启动时间的方案。


优化 Dockerfile


首先,我们可以参考官方 Stable Diffusion WebUI 安装说明,生成其 Dockerfile。在这里给大家一个参考: https://github.com/nonokangwei/Stable-Diffusion-on-GCP/blob/main/Stable-Diffusion-UI-Agones/sd-webui/Dockerfile


在初始构建的 Stable Diffusion 的容器镜像中,我们发现除了基础镜像 nvidia runtime 之外,还安装了大量的库和扩展等。


▲调优之前容器镜像大小为 16.3GB


在 Dockerfile 优化方面,我们对 Dockerfile 进行分析后,发现 nvidia runtime 约占 2GB,而 PyTorch 库是一个非常大的包,约占 5GB。另外 Stable Diffusion 及其扩展等也占据了一定的空间。因此,我们按照最小可用环境为原则,去除环境中不必要的依赖。将 nvidia runtime 作为基础镜像,然后把 PyTorch、Stable Diffusion 的库和扩展等从原始镜像中分离出来,单独存放在文件系统中。


以下是初始的 Dockerfile 的片段。


# Base image

FROM nvidia/cuda:11.8.0-runtime-ubuntu22.04


RUN set -ex &&

apt update &&

apt install -y wget git python3 python3-venv python3-pip libglib2.0-0 pkg-config libcairo2-dev &&

rm -rf /var/lib/apt/lists/*


# Pytorch

RUN python3 -m pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 --extra-index-url https://download.pytorch.org/whl/cu117



# Stable Diffusion

RUN git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git

RUN git clone https://github.com/Stability-AI/stablediffusion.git /stable-diffusion-webui/repositories/stable-diffusion-stability-ai

RUN git -C /stable-diffusion-webui/repositories/stable-diffusion-stability-ai checkout cf1d67a6fd5ea1aa600c4df58e5b47da45f6bdbf



# Stable Diffusion extensions

RUN set -ex && cd stable-diffusion-webui

&& git clone https://gitcode.net/ranting8323/sd-webui-additional-networks.git extensions/sd-webui-additional-networks

&& git clone https://gitcode.net/ranting8323/sd-webui-cutoff extensions/sd-webui-cutoff

&& git clone https://ghproxy.com/https://github.com/toshiaki1729/stable-diffusion-webui-dataset-tag-editor.git extensions/stable-diffusion-webui-dataset-tag-editor


我们在移除 Pytorch 的库和 Stable Diffusion 之后,我们只保留了基础镜像 nvidia runtime 在新的 Dockerfile 中。


FROM nvidia/cuda:11.8.0-runtime-ubuntu22.04

RUN set -ex &&

apt update &&

apt install -y wget git python3 python3-venv python3-pip libglib2.0-0 &&

rm -rf /var/lib/apt/lists/*


▲基础镜像变成了 2GB


其余的运行时类库和 extension 等存放在磁盘镜像中,磁盘镜像的大小为 6.77GB。采用磁盘镜像的好处是,它可以最多支持同时恢复 1,000 块磁盘,完全能满足大规模扩缩容的使用场景。



挂载磁盘到 GKE 节点


然而,问题来了,如何将这个单独的文件系统挂载到容器运行时中呢?一种想法是使用 Persistent VolumeClaim (PVC) 进行挂载,但由于 Stable Diffusion WebUI 在运行时既需要读取又需要写入磁盘,而 GKE 的 PD CSI 驱动程序目前不支持多写入 ReadWriteMany,只有像 Filestore 这样的 NFS 文件系统才能支持,但是通过网络挂载的 Filestore 就延迟来说仍然无法达到快速启动的效果。同时,由于 GKE 目前不支持在创建或更新 Nodepool 时挂载磁盘,所以我们考虑使用 DaemonSet 在 GKE 节点启动时挂载磁盘。具体做法如下:



那么如何将磁盘挂载到 GKE 的节点上呢?可以直接调用 Cloud SDK,创建基于磁盘镜像的磁盘。


gcloud compute disks create sd-lib-disk-$NOW --type=pd-balanced --size=30GB --zone=$ZONE --image=$IMAGE_NAME


gcloud compute instances attach-disk ${MY_NODE_NAME} --disk=projects/$PROJECT_ID/zones/$ZONE/disks/sd-lib-disk-$NOW --zone=$ZONE


利用 GKE Image Streaming

和 Cluster Autoscaler


另外,正如我们前面提到的那样,在优化镜像下载和加载时间方面,我们还启用了 GKE Image Streaming 来加速镜像的拉取速度。它的工作原理是使用网络挂载将容器数据层挂载到 containerd 中,并在网络、内存和磁盘上使用多个缓存层对其进行支持。一旦我们准备好 Image Streaming 挂载,您的容器就会在几秒钟内从 ImagePulling 状态转换为 Running (无论容器大小);这有效地将应用程序启动与容器映像中所需数据的数据传输并行化。因此,您可以看到更快的容器启动时间和更快速的自动缩放。


我们开启了 Cluster Autoscaler 功能,让有更多的请求到来时,GKE 节点自动进行弹性扩展。通过 Cluster Autoscaler 触发并决定扩展到多少个节点来接收新增的请求。当 CA 触发了新的一轮扩容,新的 GKE 节点注册到集群以后,Daemonset 就会开始工作,帮助挂载存储了 runtime 依赖的磁盘镜像,而 Stable Diffusion Deployment 则会通过 HostPath 来访问这个挂载在节点上的磁盘。


我们还使用了 Cluster Autoscaler 的 Optimization Utilization Profile 来缩短扩缩容时间、节省成本并提高机器利用率。


最后的启动效果如下:



按时序排列

触发 Cluster Autoscaler 扩容:38s

Node 启动并调度 Pod:89s

挂载 PVC:4s

启动 Pull Image:10s

拉取镜像:1s

启动 Pod:1s

能够提供 sd-webui 的服务 (大约): 65s


总共经历了大约 3 分钟的时间,就完成了启动一个新的 Stale Diffusion 容器实例,并在一个新的 GKE 节点上进行正常服务的过程。相比于之前的 12 分钟,可以看见,明显的提升启动速度改善了用户体验。


完整代码: https://github.com/nonokangwei/Stable-Diffusion-on-GCP/tree/main/Stable-Diffusion-UI-Agones/optimizated-init


通过 VolumeSnapshot


除了挂载 Disk 到 GKE 节点上,还有一种尝试,我们可以使用 StatefulSet 来挂载 PVC。


具体做法如下:先定义一个 storageclass,注意我们使用DiskImageType: images来指定 PVC从 Disk Image 来恢复,而不是 Snapshot。


Snapshot 每 10 分钟只能恢复一次,一小时以内恢复 6 次 Disk 的限制。

而 Image 可以支持每 30 秒恢复一次,最多 1,000 个 Disk。

apiVersion: snapshot.storage.k8s.io/v1

kind: VolumeSnapshotClass

metadata:

name: image-class

driver: pd.csi.storage.gke.io

deletionPolicy: Delete

parameters:

DiskImageType: images

再定义一个 VoluemSnapShotContent,它指定了 source 为一个 Disk Image sd-image


apiVersion: snapshot.storage.k8s.io/v1

kind: VolumeSnapshotContent

metadata:

name: test-snapshotcontent-from-image

spec:

deletionPolicy: Retain

driver: pd.csi.storage.gke.io

volumeSnapshotClassName: image-class

source:

snapshotHandle:projects/flius-vpc-2/global/images/sd-image

volumeSnapshotRef:

name: test-snapshot

namespace: default


接下来,我们再创建一个 VolumeSnapShot,指定它的 source 是刚刚定义的VoluemSnapShotContent。


apiVersion: snapshot.storage.k8s.io/v1

kind: VolumeSnapshot

metadata:

name: test-snapshot

namespace: default

spec:

source:

volumeSnapshotContentName:test-snapshotcontent-from-image


最后,我们创建一个 StatefulSet 来挂载这个 VolumeSnapShot。


apiVersion: apps/v1

kind: StatefulSet

metadata:

name: stable-diffusion-statefulset-image

labels:

app: stable-diffusion

spec:

podManagementPolicy: "Parallel"

replicas: 1

selector:

matchLabels:

app: stable-diffusion

template:

metadata:

labels:

app: stable-diffusion

spec:

containers:

- name: stable-diffusion-webui

image: us-central1-docker.pkg.dev/flius-vpc-2/stable-diffusion-repo/sd-webui-final:0.1

command: ["/bin/bash"]

args: ["-c", "source /runtime-lib/bin/activate; cp/user-watch.py /runtime-lib/stable-diffusion-webui/user-watch.py;cp/start.sh /runtime-lib/stable-diffusion-webui/start.sh; cd /runtime-lib/stable-diffusion-webui; python3 launch.py --listen --xformers --enable-insecure-extension-access--no-gradio-queue" ]

volumeMounts:

- mountPath: "/runtime-lib"

name: runtime-lib

resources:

limits:

nvidia.com/gpu: 1

ports:

- containerPort: 7860

volumeClaimTemplates:

- metadata:

name: runtime-lib

spec:

dataSource:

name: test-snapshot

kind: VolumeSnapshot

apiGroup: snapshot.storage.k8s.io

accessModes: [ "ReadWriteOnce" ]

storageClassName: "standard-rwo"

resources:

requests:

storage: 30Gi


我们尝试扩容更多的副本。


kubectl scale statefulset stable-diffusion-statefulset-image --replicas=15


可见 GKE 可以支持并行的启动这些 Pod,并且分别挂载相应的磁盘。



PersistentVolumeClaims



完整代码:

https://github.com/Leisureroad/volumesnapshot-from-diskimage


最终,我们可以看见如下的 Stable Diffusion 的 WebUI。






 点击屏末||了解更多 Google Cloud 技术趋势与最新解读


原文标题:优化 Stable Diffusion 在 GKE 上的启动体验

文章出处:【微信公众号:谷歌开发者】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 谷歌
    +关注

    关注

    27

    文章

    6265

    浏览量

    112157

原文标题:优化 Stable Diffusion 在 GKE 上的启动体验

文章出处:【微信号:Google_Developers,微信公众号:谷歌开发者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何使用SD卡启动模式 LS1046ardb 测试 SPI 环回?

    )短路。以下是问题: 1. 注意到 RCW 中的 SPI_EXT 和 SPI_BASE 中需要进行一些更改为“0”,通过这些更改,我们仍然可以从 SD 卡启动吗? 2. 这可以板从 SD 卡启动
    发表于 05-07 07:05

    慧荣科技于Embedded World 2026展示AI优化启动存储与企业级解决方案

    慧荣科技(NasdaqGS: SIMO)作为设计和推广固态存储设备NAND闪存主控芯片的全球领导者,于3月10日至12日德国纽伦堡举行的Embedded World 2026,展示其专为AI优化
    的头像 发表于 03-11 14:09 313次阅读
    慧荣科技于Embedded World 2026展示AI<b class='flag-5'>优化</b>的<b class='flag-5'>启动</b>存储与企业级解决方案

    PyTorch 中RuntimeError分析

    ? 错误原因 这个 RuntimeError 是因为 PyTorch 中,upsample_nearest2d_out_frame(最近邻2D采样)操作尚未对 BFloat16 数据类型提供
    发表于 03-06 06:02

    从炫技到量产,具身智能要突破哪些瓶颈?

    LingBot-VLA 开源,具身智能的 Stable Diffusion 来了?
    的头像 发表于 01-28 17:12 9217次阅读
    从炫技到量产,具身智能要突破哪些瓶颈?

    LDO性能优化的应用技巧

    本文围绕LDO性能优化的关键环节展开,系统阐述了从启动过程控制、不同负载条件下稳定工作到瞬态响应提升的全链路应用技巧。内容涵盖启动过冲抑制、电子负载CC/CR模式下的适应性
    的头像 发表于 01-22 10:24 6514次阅读
    LDO性能<b class='flag-5'>优化</b>的应用技巧

    GM9-2003/D3000主板图形适配方案:Ventoy启动与显卡兼容性优化指南

    GM9-2003/D3000飞腾商务主板使用Ventoy工具安装服务器系统时,若搭配AMD R5 230显卡,可能出现启动阶段花屏现象;而切换至MTT S30显卡则显示正常。此问题源于显卡驱动
    的头像 发表于 01-04 14:36 1433次阅读
    GM9-2003/D3000主板图形适配方案:Ventoy<b class='flag-5'>启动</b>与显卡兼容性<b class='flag-5'>优化</b>指南

    Linux系统冗余设计裁剪开机时间优化

    1、保留现有功能(RT-Linux实时特性、SPI驱动正常工作、网口通信正常、USB驱动)的前提下,将Upboard开发板的Linux系统开机时间从当前~60秒优化至≤20秒(启动
    发表于 12-16 22:17

    本地部署Stable Diffusion实现AI文字生成高质量矢量图片应用于电子商务

    本地部署Stable Diffusion
    的头像 发表于 11-28 07:19 990次阅读

    CW32时钟的启动过程

    SYSCTRL_HSE.STABLE 被置 1;如果在一定时间内未检测到 SYSCTRL_HSE.WAITCYCLE 个时钟信号则认为 HSE 振荡器起振失败。 其它时钟振荡器的时钟启动过程类似,但注意各时钟
    发表于 11-13 07:49

    润和软件优化昇腾310B启动时间

    边缘计算场景中,“启动速度”往往直接决定着设备的响应效率——工业监控设备若启动过慢,可能错过关键数据采集;智能电网边缘网关若恢复迟缓,会影响电力调度稳定性;无人机飞控设备若初始化耗时久,甚至可能延误任务执行。昇腾310B作为边
    的头像 发表于 10-14 14:06 1037次阅读
    润和软件<b class='flag-5'>优化</b>昇腾310B<b class='flag-5'>启动</b>时间

    【Sipeed MaixCAM Pro开发板试用体验】基于MaixCAM-Pro的AI生成图像鉴别系统

    手绘扫描图。该模型将被优化并部署MaixCAM-Pro边缘计算设备,使其具备离线、实时、低功耗的图片鉴别能力,可应用于艺术鉴定、内容审核、学术诚信核查等多个场景。 2. 核心目标 高精度分类:模型
    发表于 08-21 13:59

    无感FOC算法电机启动时具体如何优化性能?--【其利天下】

    现代电机控制系统中,无感FOC(磁场定向控制)算法因其卓越的性能表现而备受关注。尤其是电机启动阶段,无感FOC算法通过一系列优化措施,极大地提升了电机的
    的头像 发表于 08-08 18:38 1875次阅读
    无感FOC算法<b class='flag-5'>在</b>电机<b class='flag-5'>启动</b>时具体如何<b class='flag-5'>优化</b>性能?--【其利天下】

    无法NPU推理OpenVINO™优化的 TinyLlama 模型怎么解决?

    NPU 推断 OpenVINO™优化的 TinyLlama 模型。 遇到的错误: get_shape was called on a descriptor::Tensor with dynamic shape
    发表于 07-11 06:58

    如何在MCXN947微控制器配置安全启动和生命周期

    本文档旨在介绍如何在MCXN947微控制器配置安全启动和生命周期,以确保产品量产阶段的安全性,防止代码被窃取和篡改,并且能够安全地升级更新固件。通过本应用笔记,开发者可以更好地理解和实施安全
    的头像 发表于 06-26 09:49 2793次阅读
    如何在MCXN947微控制器<b class='flag-5'>上</b>配置安全<b class='flag-5'>启动</b>和生命周期

    鸿蒙5开发宝藏案例分享---冷启动优化案例分享

    程 ?非必要资源延迟加载 ?首屏数据本地缓存优先 优化后我们的应用冷启动速度提升300%+!这些宝藏案例都在官方性能优化文档中,强烈建议大家仔细研究。 最后送大家一句话 :性能优化不是
    发表于 06-12 17:22