使用 PAI-Blade 优化 Stable Diffusion 推理流程
背景
AIGC是人工智能计算领域里发展迅速的重要业务。Stable Diffusion 是其中最热门的开源模型,受到广泛关注。然而,随着应用场景不断扩大,Stable Diffusion所面临的推理时延和计算成本问题也越来越突出。
简介
PAI-Blade是 PAI 推出的通用推理优化工具,可以通过模型系统联合优化,使模型达到最优推理性能。PAI-Blade依托于完全动态尺寸的AI编译器BladeDISC 和 基于深度学习自动调度的高性能计算库BlaDNN, 为包括图像生成模型Stable Diffsuion, 大语言模型LLM, 大规模稀疏推荐模型CTR, 语音识别模型ASR等等在内的众多模型提供自动的高性能推理优化。
BladeDISC 是一款支持完全动态尺寸的AI编译器,前端支持Pytorch和Tensorflow模型。对于Pytorch模型能够支持 TorchScript 和 TorchDynamo 两种输入模式,后端通过 AStitch 大尺度算子融合技术和高效的 codegen 逻辑提升模型访存密集算子的执行效率。BladeDISC现已在github开源,项目地址:https://github.com/alibaba/BladeDISC 。
BlaDNN 是基于深度学习自动调度的高性能计算库。BlaDNN 作为Ansor的升级版,不仅生成的kernel性能超过Ansor,而且可以完全依赖DNN自动调度而不使用Tuning调优,使得Dynamic Shape业务场景的在线自动调度成为可能,基于DNN自动调度生成的GPU计算密集算子的平均性能达到极致tuning性能的99.39%,通过模型系统联合优化DNN推理延时低至2us, 并且只使用一个CPU Core,从而不会对GPU模型本身的性能造成任何抖动。
通过采用 PAI-Blade 加速推理优化技术,对访存密集型算子进行大尺度融合及优化代码生成,对计算密集型算子进行自动调度,可以大幅度降低Stable Diffusion的推理延迟和显存占用,从而减少计算成本。使用 PAI-Blade 优化Stable Diffusion 具有以下三点优势:
- 高性能,使用Blade可以降低 Text2Img、Img2Img 等推理流程的端到端延迟 2.42-3.05 倍,同时可降低省显存占用至多 5.27 倍,超过TensorRT-8.5等业内SOTA优化手段。
- 完全动态shape支持,一次优化后,可以支持任意形状、batch size的输入。
- 易用性、可扩展性:仅需数行代码即可在多类pipeline中启用 Blade优化,同时能支持LoRA等推理方案的优化。
使用示例
本文接下来以社区流行的 "runwayml/stable-diffusion-v1-5" 的 Text2Img pipeline 为例,详细介绍 PAI-Blade 在各类使用场景下的使用方法。
环境安装
下述示例完整的运行脚本及相关环境已集成到 registry.cn-beijing.aliyuncs.com/blade_demo/blade_diffusion
docker 中。在该docker中,直接通过 python /blade/blade_diffusion.py
即可运行推理示例。
官方模型优化
使用 PAI-Blade 优化 Stable Diffusion 模型可以分为以下几个步骤。
首先,加载预训练的模型。
from diffusers import StableDiffusionPipeline device = torch.device("cuda:0") pipe = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", revision="fp16", torch_dtype=torch.float16).to(device)
第二步,使用 PAI-Blade 进行优化。注意,由于 PAI-Blade 是完全动态shape的优化工具,优化完成后可使用任意shape进行推理。
import torch_blade opt_cfg = torch_blade.Config() opt_cfg.enable_fp16 = True with opt_cfg, torch.no_grad(): encoder = blade_optimize(pipe.text_encoder, model_inputs=encoder_inputs, allow_tracing=True) unet = blade_optimize(pipe.unet, model_inputs=unet_inputs, allow_tracing=True) decoder = blade_optimize(pipe.vae.decoder, model_inputs=decoder_inputs, allow_tracing=True)
最后,使用优化好的模型替换原始模型,后续即可以原始 pipeline 同样的方式进行推理。
@dataclass class UNet2DConditionOutput: sample: torch.FloatTensor class TracedUNet(torch.nn.Module): def __init__(self): super().__init__() self.config = pipe.unet.config self.in_channels = pipe.unet.in_channels self.device = pipe.unet.device def forward(self, latent_model_input, t, encoder_hidden_states, **kwargs): sample = unet(latent_model_input.half(), t.half(), encoder_hidden_states.half())["sample"] return UNet2DConditionOutput(sample=sample) class TracedEncoder(torch.nn.Module): def __init__(self): super().__init__() self.config = pipe.text_encoder.config self.device = pipe.text_encoder.device self.dtype = torch.half def forward(self, input_ids, **kwargs): embeddings = encoder(input_ids.long()) return [embeddings["last_hidden_state"]] class TracedDecoder(torch.nn.Module): def forward(self, input): return decoder(input.half()) pipe.text_encoder = TracedEncoder() pipe.unet = TracedUNet() pipe.vae.decoder = TracedDecoder()
A100 性能对比
image size | samplesteps | Time of Pytorch(s) | Time of PAI-Blade(s) | speedup | Pytorch memory usage (GB) | PAI-Blade memory usage (GB) |
---|---|---|---|---|---|---|
1024x1024 | 50 | 13.26 | 4.34 | 3.06X | 32.91 | 6.25 |
768x768 | 50 | 5.65 | 2.00 | 2.83X | 14.99 | 5.91 |
512x512 | 50 | 2.24 | 0.84 | 2.67X | 6.60 | 5.42 |
A10 性能对比
image size | samplesteps | Time of Pytorch(s) | Time of PAI-Blade(s) | speedup | Pytorch memory usage (GB) | PAI-Blade memory usage (GB) |
---|---|---|---|---|---|---|
1024x1024 | 50 | OOM | 13.86 | - | OOM | 6.89 |
768x768 | 50 | 13.13 | 5.61 | 2.34X | 12.60 | 6.22 |
512x512 | 50 | 4.53 | 2.11 | 2.15X | 6.28 | 5.47 |
推理结果验证
使用PAI-Blade优化后,生成的图像与Pytorch原始输出对比,观察优化结果是否正确。左图为Pytorch eager模式输出,右图为PAI-Blade优化后的模型输出。
已验证的pipeline类型
- StableDiffusionPipeline
- StableDiffusionImg2ImgPipeline
- StableDiffusionInpaintPipeline
- AltDiffusionPipeline
LoRA优化
LoRA 是指在原始模型基础上,添加额外的低秩矩阵来微调预训练的模型,并且只训练那些新添加的权重,从而大幅降低微调成本。可以通过 diffusers官方训练代码 微调得到 LoRA 权重。diffusers 加载使用 LoRA 后,模型运行方式与原始模型略有不同,带来额外计算开销。
PAI-Blade 目前已适配 huggingface/diffusers 中 LoRA 优化方式。同样的,Blade 针对同一pipeline,只需优化一次,即可使用任意的 LoRA 权重进行推理。我们将在下一篇文章中介绍PAI-Blade 优化 LoRA 的使用方式,敬请期待。
展望
目前,Stable Diffusion相关技术仍在不断演化中,PAI-Blade 团队也时刻关注社区趋势,将优化适配到各种工具中去。目前团队主要集中在:
- 将相关优化集成到 stable-diffusion-webui 中;
- 优化 finetune 训练速度。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Deferred Components-实现Flutter运行时动态下发Dart代码 | 京东云技术团队
导读 Deferred Components,官方实现的Flutter代码动态下发的方案。本文主要介绍官方方案的实现细节,探索在国内环境下使用Deferred Components,并且实现了最小验证demo。读罢本文,你就可以实现Dart文件级别代码的动态下发。 一、引言 Deferred Components是Flutter2.2推出的功能,依赖于Dart2.13新增的对Split AOT编译支持。将可以在运行时每一个可单独下载的Dart库、assets资源包称之为延迟加载组件,即Deferred Components。Flutter代码编译后,所有的业务逻辑都会打包在libapp.so一个文件里。但如果使用了延迟加载,便可以分拆为多个so文件,甚至一个Dart文件也可以编译成一个单独的so文件。 这样带来的好处是显而易见的,可以将一些不常用功能放到单独的so文件中,当用户使用时再去下载,可以大大降低安装包的大小,提高应用的下载转换率。另外,因为Flutter具备了运行时动态下发的能力,这让大家看到了实现Flutter热修复的另一种可能。截止目前来讲,官方的实现方案必须依赖Goog...
- 下一篇
DPDK内存碎片优化,性能最高提升30+倍!
原文链接点击 DPDK内存碎片优化,性能最高提升30+倍! 背景 DPDK(Data Plane Development Kit)是一个用于高性能数据包处理的开源项目,常用于构建各类高性能网络应用。基于 DPDK 的设计思想及其提供的线程/内存模型,SPDK(Storage Performance Development Kit)被开发出来,广泛用于构建各类高性能存储应用。 为了提升应用程序的性能,DPDK 基于大页内存实现了一套自己的内存管理接口,这些内存接口被广泛应用于SPDK/DPDK 的各类应用中,而且不少应用会在 IO 路径中进行内存的分配与释放。DPDK 常用的内存接口有: void *rte_malloc(const char *type, size_t size, unsigned align); void *rte_realloc(void *ptr, size_t size, unsigned int align); void rte_free(void *ptr); 在实际使用过程中,我们发现 DPDK 原生的内存分配接口在一些场景下有着较大的性能问题。本文将结合...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19