接上文,https://developer.aliyun.com/article/1352214
六、Stable Diffusion 推理优化 - DeepGPU 实例
1. 市场常用的推理框架
对 Stable Diffusion 推理,友商主流的推理加速方案目前基本使用的是社区级框架,其中以 xFormers&TensorRT 较为常用。xFormers 基本可以代表社区级推理的效率顶峰,TensorRT 是 NVIDIA 原厂的 Tensor 加速框架。
2. 阿里云 DeepGPU 实例优化项
DeepGPU 实例,即嵌入了 AIACC 3.0 套件的 ECS GPU 实例。阿里云推出的 DeepGPU,实现了相较原生 PyTorch 2.5-6 倍的提升,相较社区级领先框架 xFormers 1.5-2.3 倍的提升。从单点推理性能上来讲独步整个市场。那么,这样的性能是如何实现的?
前文有详细介绍 Stable Diffusion 模型组件的基本结构,大家可以观察到,推理过程涉及到的 GPI 运算操作,原子级的操作就是各种矩阵运算的算子。DeepGPU,基于 CUDA ptx 几乎完整构建了我们自有的算子库,针对 Stable Diffusion 我们将算子库分为 3 类:
计算密集:matmul 类算子,DeepGPU 根据模型计算单元逻辑情况,定制了大量 kernel,包括但不限于各类 fusion 操作,以及与 conv 层、gemm 层组合算子,这样做的好处是,组合算子可以在单次访存时间内实现多次计算操作。
混合型:attention 类,对广泛存在于 Stable Diffusion 内的 attention 机制,单独定制了 kernel 实现高效率计算 attention 连接。社区级框架往往依然使用多步算子计算或调用额外算子库来实现。
访存密集:针对 Stable Diffusion 大量的 softmax、layernorm 等汇聚计算,DeepGPU 单独定制了 reduce 类 kernel 来进进行计算结果汇聚的优化,旨在解决不同子网计算结果的高效汇聚。特别的,对于 elementwse 逐元素操作,不涉及计算仅涉及读写的,同样定制了对应的 fusion 算子。对访存密集的操作,L0、L1 cache 的分配是至关重要的。除了需要考虑 GPU SM 间以及 TPC 间物理 cache 共享情况外,依据线程负载、数据块尺寸的动态分配和访存重叠策略能进一步挖掘 GPU 计算资源的极致性能。
特别的,DeepGPU 支持模型的张量和流水线切分,但是切分会有切分模块计算结果广播、收集的开销。这部分优化主要针对需要进行显存突破的场景尤其是 LLM,在 Stable Diffusion 上应用较少,我们往往会通过选择合适的 GPU 来规避切分。
DeepGPU 核心是 kernel 的优化,除此之外,在推理链路上,同样做了一系列的优化措施:
缓存优化:尽可能使用高速缓存的同时,引入数据分块策略,划分合理的数据块避免一次运算所需数据进行 2 次读写;同时在高速缓存区设置双缓存策略,在单 SM/计算单元视角,上一个计算任务进行时,将下一个计算任务所需的数据预热到高速缓存。
计算/并发优化:针对单核计算任务进行线程负载优化,并分配合理的寄存器支撑计算流水作业;针对众核计算任务进行线程并发控制,根据时间轮片上可用的计算资源和寄存器资源寻找合适的线程并发数。
带宽优化:显存带宽对于 GPU 来说非常珍贵,针对模型加载至显存过程,充分挖掘可用显存带宽。
3. 性能对比
通过上述一系列的优化措施,我们取得了业内领先的性能表现,从推理耗时测试可以直观地看到 DeepGPU 单点推理效率数倍于社区级框架,从而助力客户极大提升 GPU 资源使用效率。
这里公布一组推理实测数据:
batch1 1024*1024 20 steps出图,极致优化可以做到A10 GPU 3.95s出图,A100 GPU 1.55s出图。如有其他测试诉求,欢迎登陆阿里云计算巢,使用DeepGPU测试应用进行进一步测试。
应用文档地址:https://aliyun-computenest.github.io/quickstart-stable-diffusion-aiacctorch/
七、 Stable Diffusion 推理优化 - Fluid 分布式缓存
1.痛点出现
因 Stable Diffusion 推理场景有个重要的特点:随着服务用户需求的增长,会产生大量的底模 (8k+)、LoRA(1w+)、ControlNet(15+)组合,这样庞大的推理模型组合是无法长期全量保持在内存中的。
如果采取低成本存储介质进行保持,那么下沉到用户请求颗粒度的模型切换诉求会导致整个方案瓶颈卡在存储介质性能上,我们实测也会发现远远无法释放 DeepGPU 推理优化的性能。
一个实际的测试用例可能更容易理解:
DeepGPU 实现了一种底模组合推理从 16s 到 4s 的优化,节省了 12s。但是面对峰值用户请求,可能需要上千种模型组合不断进入 GPU 进行单点推理,而 Stable Diffusion 底模典型尺寸在 4GB 左右,LoRA 在百 MB 左右,ControlNet 在几十 MB 左右,这时模型切换需要从存储介质读取入实例内存,再加载到 GPU 显存,这个链路中,对单次请求存储介质加载时间可能会增加 3-4s,而并发请求这个值可能会攀升到分钟级(包括请求队列等待时间),这样 DeepGPU 优化的 12s 性能优势完全无法释放。
2.优化方案
针对这样的痛点场景,我们提出了由云原生团队负责的 Fluid 分布式缓存方案。Fluid 文件系统是开源的文件系统,通过将模型进行切片存储,并将一次读取请求映射为拉起多个线程的网络 IO 读取行为,实现跨实例的模型加载。这一过程,模型典型切片包大小为 4MB,读取行为整包内容用并发的线程来拉取到计算节点的内存,整体读取性能得到巨大的提升。因并发线程行为相当于将存储 IO 转换为了网络 IO,所以在请求并发情况下,限制读取性能的瓶颈值从存储介质的存储带宽提升到了 VM 的网络带宽上限。
同时 Fluid 文件系统支持直接架设在计算节点上,也就是说随着计算节点保持规模上升,Fluid 可用内存池会不断扩大,这样可以随着内存池扩容情况逐步将全量模型数据预热到内存池中,从而实现模型内存命中率不断提升。
当然 Fluid 文件系统也支持混合架设在计算节点实例和网络增强型实例上,这样通过内存预设管理,可以实现更强的读取上限。
通过 Fluid 分布式缓存方案,绕开了存储介质带来的成本、性能瓶颈,进一步的,池化的内存也实现了计算 GPU 资源与内存的解耦,我们可以不需要过分关注 GPU 实例的内存与 GPU 配比。当然,相比于一机单卡实例,一机多卡实例 GPU 共享的物理内存面更大,在峰值性能上更具优势。
通过 Fluid 分布式缓存,我们实测完全可以释放 DeepGPU 的推理性能。Fluid 对高频模型加载性能,在 gn7i 单卡实例上甚至可以与单盘 NAS 持平而无需增加任何成本。
八、Stable Diffusion 推理优化 - 业务稳定性
对于一个商业化方案,业务稳定性自然是重中之重。我们在孵化 DeepGPU + Fluid 方案的同时,同样充分考虑了业务弹性与容灾的问题。
1.业务弹性
在 DeepGPU+Fluid 架构下,我们通过使用 ACK 的集群管理,实现对 DeepGPU 弹性扩容与 Fluid 节点弹性扩容的管理策略,在 Prometheus 上设置合理的 Metrics,对计算负载进行动态监控。同时引入客户 Pulsar 队列指标,进一步预判计算资源需求的需求扩增,提前预热计算节点。后续我们计划使用 Grafana 来进一步做集群管理的可视化。
2.业务容灾
DeepGPU + Fluid 架构,最大的优点是使用的均是阿里云上标准的 IaaS 和 PaaS 服务,从而允许我们较为轻松地实现双 AZ 容灾策略。在多 AZ 容灾配置过程中,仅需针对 Pulsar 请求队列的投递配置合适的负载均衡策略,即可实现业务容灾及平滑的宕机迁移。
九、GPU 关键指标及选型
DeepGPU + Fluid 架构的标准化带来的一个优势就是,所有阿里云上的 GPU 实例均可部署该架构。
进一步的, AIACC 团队在服务大量的 Stable Diffusion 案例中,使用 DeepGPU 实例对多种阿里云上的 GPU 实例进行了充分的性能测试。总结出一套切实有效的 GPU 选型推荐策略。所以针对 Stable Diffusion 推理应用,可以直观地按照推荐度进行直接选型。
十、Stable Diffusion 交付 - 标准交付件&交付工作流
1.交付形态
目前 DeepGPU + Fluid 架构,支持封闭架构形式的计算巢交付,这个应用即将借助 HY 项目落地并支撑客户进行下游 B 端交付。
同样的,开放架构的 CADT 交付同样可取,在开放 CADT 架构中,我们将一定程度地简化架构,形成标准的开放架构交付模块。
对于 Stable Diffusion 深度客户,在上述交付件无法满足需求时,我们也支持定制的架构设计及交付。
2.交付工作流
i. 客户背景能力评估
普遍地,我们对 Stable Diffusion 应用客户,需要首先进行一定的能力评估。这个评估至关重要,我们需要对客户的数据资产能力进行一定的预判,来确保客户当前设计的商业模式具有足够的市场活力和竞争力。
其次对客户应用端服务能力评估,也将直接决定我们设计架构与划定架构落地和交付工作的边界。我们致力于为客户提供端到端的服务,但是我们认为交付与客户能力匹配的交付件是对一个商业化项目最高效的模式。
ii. 应用服务及架构设计
评估完成后,我们有了明确的需求范围、项目范围及交付基准,接下来可以在范围内进行充分的应用服务平面及推理架构设计,寻找符合客户场景最优的服务平面形态与推理架构,这一过程不但要考虑客户应用端的耦合性,同时更要考虑我们做出的应用端设计是否具备市场竞争力及可复制性。
如果客户提出高度定制化应用服务平面要求,建议在不影响项目落地的情况下尽可能引导客户走向通用行业标准的应用端平面或阿里云已有的平面能力,例如已经成熟的 Open API 作为服务平面原子能力。
对于推理架构,需要综合考虑客户应用请求的特征,是否具备大规模模型切换读取及什么类型的读取,进一步考虑推理与应用服务之间请求传递的桥接是否具有足够鲁棒性,是否具有足够的上限确保极致性能的释放。在此基础上,根据性价比向客户推荐架构内独立节点选型,选择合适的 DeepGPU 实例,来搭建推理架构。
上述架构在设计阶段都需要考虑必要的性能埋点,以便抓去关键性能指标。
iii. PoC 与客户压测
上述设计完成后,无论应用端还是推理端均需做足够的 PoC 及客户真实请求压测。这一过程往往可以提早暴露架构设计的不合理之处同时可以收集整体架构性能埋点的关键数据,一方面可以面向客户做合理的性能论证,另一方面也有助于我们进行架构方案的迭代。
客户压测,对我们设计架构来说,是面向客户建立信心的最关键阶段。我们需要在进入压测之前进行充分的内部压测模拟,确保客户侧压测顺利通过。压测的顺利,往往对后续客户上量有很好的促进作用。
iv. 正式上线与流量导入
完成上述步骤后,相信我们与客户之间已经建立了充分的信任和粘性,此时可以进一步摸排客户真实需求分布,引导客户进行逐步的灰度迁移。
在这一阶段,我们可以与客户进行额外的互动,支持或协同客户做一些开服、引流的 PR,对我们产品能力及客户市场影响力有双赢的效果。
v. 交付正式运营
这一阶段是整体服务架构的正式割接阶段,我们需要根据项目中双方开发内容对接情况设定完整的割接手续,完成割接后,对于项目支持我们将从方案架构主导角色彻底转为技术支持角色。在交付后客户进一步的创新内容,将是客户自己的知识产权,同样的,创新带来的提升或架构问题,也应以客户主导,阿里云提供技术支持的模式解决。
vi. 可选-计算巢上线
客户业务形态可能性有很多,我们可以支持客户根据交付的方案架构或叠加二次创新的架构在计算巢上线应用,以满足客户进一步拓展下游的 B 端需求。计算巢应用,可以根据客户的偏好来设定全托管还是私有部署模式。
十一、商业化案例
某客户商业化案例如上,基本原理和基本架构在前文已经有了充分的介绍。
其实在初始架构设计阶段,我们认为直接对 GPU 实例架设 Fluid 实现计算内存池化是性价比最优的方案。这样即可以对客户保有计算资源有一定正向促进作用,同样可以减少计算实例在使用中的内存碎片。
但是实际业务跑下来发现,客户可能对这类的性价比策略不是特别满意。计算资源 DeepGPU 实例的内存满载,会有 OOM 的风险,另外计算操作的全量热模型缓存需要全部舍弃。
对于客户这类诉求,我们最终设计了计算资源 DeepGPU 实例与网络增强型实例进行内存混合池化的策略。
DeepGPU 实例的内存分配:缓存热点完整模型+运行内存+ Fluid 拉取 buffer+通用 buffer
网络增强型实例的内存分配:全量提供 Fluid 内存池
这种方案会增加一定的成本,但是同样进一步提升了 Fluid 读取的瓶颈,最终成为了客户实际商业化落地的模式。
当前 HY 刚刚完成商业化交付,处于存量用户导入阶段。即将进行服务割接。相信以 HY 目前 Stable Diffusion 领域全球前十的行业地位,未来可以基于阿里云的技术支持大放异彩。
以上内容,是根据商业化案例进行的一次总结,基于这个案例,我们遍历编译了超过 8 千种 Stable Diffusion 底模,超过 1 万种 LoRA,将 DeepGPU 实例推向了成熟;同时测试优化了 Fluid 分布式缓存方案,引入 juicefs 组件改善了文件切片及读取瓶颈;也开发了优化的模型哈希算法可以进一步节省全链路时长。
通过这个案例,我们孵化出了标准的 Stable Diffusion IaaS+ 推理解决方案,固化了高度标准化、模块化的交付形式,相信可以在 AIGC Stable Diffusion 文生图、图生图领域获得更多的案例复制。
本文到此完结,关于架构部分,叙述较为粗浅,可能很多观点囿于行业视野与项目经验,请各位读者不吝斧正!
感谢阅读!欢迎任何形式的交流!
阿里云弹性计算 PDSA
丁祎程(益成)
2023 年 10 月 17 日