使用 PAI-Blade 优化 Stable Diffusion 推理流程(二)

背景

上一篇中,我们使用了 PAI-Blade 优化了 diffusers 中 Stable Diffusion 模型。本篇,我们继续介绍使用 PAI-Blade 优化 LoRA 和 Controlnet 的推理流程。相关优化已经同样在 registry.cn-beijing.aliyuncs.com/blade_demo/blade_diffusion镜像中可以直接使用。同时,我们将介绍 Stable-Diffusion-webui 中集成 PAI-Blade 优化的方法。

LoRA优化

PAI-Blade优化LoRA的方式,与前文方法基本相同。包括:加载模型、优化模型、替换原始模型。以下仅介绍与前文不同的部分。

首先,加载Stable DIffusion模型后,需要加载LoRA权重。

pipe.unet.load_attn_procs("lora/")

使用LoRA时,用户可能需要切换不同的LoRA权重,尝试不同的风格。因此,PAI-Blade需要在优化配置中,传入freeze_module=False,使得优化过程中,不对权重进行编译优化,从而不影响模型加载权重的功能。通过这种方式,PAI-Blade优化后的模型,依然可以使用pipe.unet.load_attn_procs()方式加载LoRA的权重,而不需要重新编译优化。

由于模型权重未进行优化流程,一些对常量的优化无法进行,因此会损失部分优化空间。为了解决性能受损的问题,PAI-Blade中,使用了部分patch,对原始模型进行python层级的替换,使得模型更适合PAI-Blade优化。通过在优化前,使用 torch_blade.monkey_patch优化 Stable Diffusion 模型中的 unet和vae部分,能更好的发挥PAI-Blade能力。

from torch_blade.monkey_patch import patch_utils

patch_utils.patch_conv2d(pipe.vae.decoder)
patch_utils.patch_conv2d(pipe.unet)

opt_cfg = torch_blade.Config()
...
opt_cfg.freeze_module = False
with opt_cfg, torch.no_grad():
    ...

如果没有LoRA权重切换的需求,可以忽略上述步骤,获得更快的推理速度。

Benchmark

我们在A100/A10上测试了上述对LoRA优化的结果,测试模型为 runwayml/stable-diffusion-v1-5,测试采样步数为50。

ControlNet适配

根据 ControlNet 的模型结构图以及diffusers中ControlNet实现,可以将ControlNet的推理分为两部分。

  1. ControlNet部分,其input blocks和 mid block 结构与Stable DiffusionUnet的前半部分相同,剩余部分为卷积。ControlNet所有输出传入到Stable DIffusion的Unet中,作为输入;
  2. Stable Diffusion 的Unet除了原始输入外,额外增加了ControlNet的输出作为输入。

根据上述特点,我们可以做出以下的优化:

首先,优化ControlNet,

controlnet = torch_blade.optimize(pipe.controlnet, model_inputs=tuple(controlnet_inputs), allow_tracing=True)

在优化unet模型时,由于torch2.0之前的版本,torch.jit.trace不支持使用dict作为输入,所以我们使用Wrapper包装Unet后便于trace和优化。同时,使用优化后的ControlNet执行一次推理,将其输出添加到Unet输入中。

class UnetWrapper(torch.nn.Module):
    def __init__(self, unet):
        super().__init__()
        self.unet = unet

    def forward(
        self,
        sample,
        timestep,
        encoder_hidden_states,
        down_block_additional_residuals,
        mid_block_additional_residual,
    ):
        return self.unet(
            sample,
            timestep,
            encoder_hidden_states=encoder_hidden_states,
            down_block_additional_residuals=down_block_additional_residuals,
            mid_block_additional_residual=mid_block_additional_residual,
        )

...
down_block_res_samples, mid_block_res_sample = controlnet(*controlnet_inputs)
unet_inputs += [tuple(down_block_res_samples), mid_block_res_sample]
unet = torch_blade.optimize(UnetWrapper(pipe.unet).eval(), model_inputs=tuple(unet_inputs), allow_tracing=True)

结合上述功能,可以同时实现:

  1. LoRA权重替换;
  2. ControlNet权重替换,来使用不同ControlNet model。

benchmark

我们在A100/A10上测试了上述对ControlNet优化的结果,测试模型为 runwayml/stable-diffusion-v1-5,测试采样步数为50。

image.png

小结

在上述部分,我们使用了PAI-Blade优化了Stable DIffusion模型的encoder、unet、decoder部分,大幅降低推理延时的同时,减少了显存占用,从而降低Stable DIffusion模型推理成本。同时,PAI-Blade支持了LoRA、ControlNet等常用功能,扩展了PAI-Blade的实用性。

webui适配

stable-diffusion-webui 是 Stable DIffusion非常热门的应用,PAI-Blade 同样提供了对其优化支持。目前,PAI-Blade已经支持了模型权重切换、LoRA、ControlNet等webui中常用的功能,同时通过 extension 的形式集成,可以便于用户使用。目前,相关优化已经集成到 PAI-EASeas-registry.cn-hangzhou.cr.aliyuncs.com/pai-eas/sdwebui-inference:0.0.2-py310-gpu-cu117-ubuntu2204-blade 镜像,可以通过PAI_EAS直接体验PAI-Blade的优化能力。

下面介绍该插件中,PAI-Blade在webui中优化方式和性能。webui优化原理与diffusers大致相同,以下是几个主要不同点:

分模块优化Unet和ControlNet

由于webui中,ControlNet需要逐个调用Unet的子模块,为了兼顾ControlNet,PAI-Blade并没有像diffusers中一样,优化整个Unet和ControlNet。而是采取逐个子模块优化的方法,将Unet、ControlNet中所有的down blocks、 mid block、up blocks分别进行优化和替换。经过测试,此种优化方式几乎不影响模型推理速度。

不冻结权重

webui的网页上,可以快捷的切换模型权重。因此,PAI-Blade采取和diffusers中LoRA优化同样的方法,不对权重进行优化。

LoRA优化

webui中,多个LoRA会逐个调用LoRA计算,计算时间随LoRA数量增多而变长。PAI-Blade 在加载LoRA权重时,将多个LoRA的权重与scale预先fuse,减少了运行时的开销。加载和fuse的开销,经测试可忽略不计。

Benchmark

我们在A10上测试了webui中,Stable DIffusion V1 模型在 batch size为1,分辨率为512*512条件下的推理速度。由于webui中涉及到网络传输等模型无关部分的延迟,因此本部分只测试了模型部分耗时。结果如下:

由该表可知,webui在eager和xformers模式下,推理时间随LoRA数量增加而延长,而PAI-Blade将所有LoRA的权重融合到基础模型,所以推理时间与LoRA数量无关。

总结

这两篇文章中,我们介绍了PAI-Blade 在Stable DIffusion模型上的优化经验,目前已经支持了Diffusers和Stable-DIffusion-webui 两种主流推理方式。

我们调研了相关公开的竞品对Stable Diffusion的支持情况,结果如下:

框架/模型 Base Model LoRA ControlNet webui
xformers
AITemplete
OneFlow
TensorRT
PAI-Blade

根据公开性能数字和业务实测,PAI-Blade对Stable DIffusion模型,不仅支持最为全面,同时性能和显存使用也是最佳水平。

目前PAI-Blade已经陆续在相关业务中上线使用。接下来,我们将继续优化性能,完善相关功能支持。欢迎大家交流、联系和合作~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容