EdVince / Stable-Diffusion-NCNN

Stable Diffusion in NCNN with c++, supported txt2img and img2img
BSD 3-Clause "New" or "Revised" License
1k stars 95 forks source link

所以还是固定512x512输出么... #1

Closed Klanly closed 1 year ago

Klanly commented 2 years ago

当初也想搞这玩意不过发现ncnn没法handle动态二维形状, 想说等它支持shape了再说...

还有我看assets/UNetModel-fp16.param, 貌似pnnx没把那一大坨MatMul-Softmax优化成MultiHeadAttention, 原版用einsum的jit code整理后如下: diffusion_embJITbase.py.txt attn1和attn2改成nn.MultiHeadAttention后应该是这样: diffusion_embJITnative.py.txt

这里有些改用nn.MultiHeadAttention的JIT .pt: https://huggingface.co/Larvik/sd470k_a300/tree/main (参考Ailia https://github.com/axinc-ai/ailia-models/issues/830 的三分UNet)

调用JIT为:

diffusion_emb = torch.jit.load('diffusion_emb_pnnx.pt')
...
  h, emb, hs = diffusion_emb(x, t, cond)

  h = diffusion_mid(h, emb, cond, *hs[6:])

  output = diffusion_out(h, emb, cond, *hs[:6])

pnnx应为:

pnnx diffusion_emb.pt inputshape=[1,4,64,64]f32,[1]i64,[1,77,768]f32
pnnx diffusion_mid.pt inputshape=[2,1280,4,8]f32,[2,1280]f32,[2,77,768]f32,[2,640,8,16]f32,[2,1280,8,16]f32,[2,1280,8,16]f32,[2,1280,4,8]f32,[2,1280,4,8]f32,[2,1280,4,8]f32
pnnx diffusion_out.pt inputshape=[2,1280,16,32]f32,[2,1280]f32,[2,77,768]f32,[2,320,32,64]f32,[2,320,32,64]f32,[2,320,32,64]f32,[2,320,16,32]f32,[2,640,16,32]f32,[2,640,16,32]f32

不过pnnx崩了 @nihui

EdVince commented 2 years ago

是的,现在输出固定是512*512。

  1. 从某种意义上来说,这个项目并不具有实用性,所以对动态shape的支持没那么优先。动态shape的问题在于,diffusion其实是一个transformer结构cv模型,对动态shape的兼容并没有那么好做。
  2. multiheadattention的确是老大难,转ncnn经常认不出来。但老实说,multiheadattention的ncnn并没有x86的优化,arm的粗略实现还是我写的,所以在x86上目前还是跑naive的,所以转不转也没差。
Klanly commented 2 years ago

torch有个_native_multi_head_attention可以参考: https://pytorch.org/cppdocs/api/function_namespaceat_1aa4f72ac82c15c7aeef274332b25a543b.html

改用nn.MultiheadAttention就为的是让torch调用这个c api. 省显存用的, 原理大约和xformers, FlashAttention差不多. https://github.com/facebookresearch/xformers https://github.com/HazyResearch/flash-attention

EdVince commented 2 years ago

kpi+++++ 我想办法优化一下这个速度吧,现在确实是慢了点,体验比较糟糕。

nihui commented 2 years ago

当初也想搞这玩意不过发现ncnn没法handle动态二维形状, 想说等它支持shape了再说...

还有我看assets/UNetModel-fp16.param, 貌似pnnx没把那一大坨MatMul-Softmax优化成MultiHeadAttention, 原版用einsum的jit code整理后如下: diffusion_embJITbase.py.txt attn1和attn2改成nn.MultiHeadAttention后应该是这样: diffusion_embJITnative.py.txt

这里有些改用nn.MultiHeadAttention的JIT .pt: https://huggingface.co/Larvik/sd470k_a300/tree/main (参考Ailia axinc-ai/ailia-models#830 的三分UNet)

调用JIT为:

diffusion_emb = torch.jit.load('diffusion_emb_pnnx.pt')
...
  h, emb, hs = diffusion_emb(x, t, cond)

  h = diffusion_mid(h, emb, cond, *hs[6:])

  output = diffusion_out(h, emb, cond, *hs[:6])

pnnx应为:

pnnx diffusion_emb.pt inputshape=[1,4,64,64]f32,[1]i64,[1,77,768]f32
pnnx diffusion_mid.pt inputshape=[2,1280,4,8]f32,[2,1280]f32,[2,77,768]f32,[2,640,8,16]f32,[2,1280,8,16]f32,[2,1280,8,16]f32,[2,1280,4,8]f32,[2,1280,4,8]f32,[2,1280,4,8]f32
pnnx diffusion_out.pt inputshape=[2,1280,16,32]f32,[2,1280]f32,[2,77,768]f32,[2,320,32,64]f32,[2,320,32,64]f32,[2,320,32,64]f32,[2,320,16,32]f32,[2,640,16,32]f32,[2,640,16,32]f32

不过pnnx崩了 @nihui

nn.MultiHeadAttention 转换确实还有问题,没有考虑 q k v 不同shape的情形。。。

https://github.com/Tencent/ncnn/pull/4347 在修了

superowner commented 2 years ago

是的,现在输出固定是512*512。

  1. 从某种意义上来说,这个项目并不具有实用性,所以对动态shape的支持没那么优先。动态shape的问题在于,diffusion其实是一个transformer结构cv模型,对动态shape的兼容并没有那么好做。
  2. multiheadattention的确是老大难,转ncnn经常认不出来。但老实说,multiheadattention的ncnn并没有x86的优化,arm的粗略实现还是我写的,所以在x86上目前还是跑naive的,所以转不转也没差。

大佬大佬,这个unet的onnx怎么转换的,有没有方法啊,是把naifu的ckpt文件直接转化为unet还是怎么搞的,还是用官方的diffuse包的转?我看原模型至少有4g啊,为什么您转换出来的只有不到2g呢

EdVince commented 2 years ago

是的,现在输出固定是512*512。

  1. 从某种意义上来说,这个项目并不具有实用性,所以对动态shape的支持没那么优先。动态shape的问题在于,diffusion其实是一个transformer结构cv模型,对动态shape的兼容并没有那么好做。
  2. multiheadattention的确是老大难,转ncnn经常认不出来。但老实说,multiheadattention的ncnn并没有x86的优化,arm的粗略实现还是我写的,所以在x86上目前还是跑naive的,所以转不转也没差。

大佬大佬,这个unet的onnx怎么转换的,有没有方法啊,是把naifu的ckpt文件直接转化为unet还是怎么搞的,还是用官方的diffuse包的转?我看原模型至少有4g啊,为什么您转换出来的只有不到2g呢

并不是的,你下载下来的4G ckpt,它里面有好几个模型,其中diffusion使用的unet模型,fp32下也就不到4G,我转出来的onnx是fp16的,因为onnx超过2G就会自动拆包。

hubin858130 commented 2 years ago

kpi+++++ 我想办法优化一下这个速度吧,现在确实是慢了点,体验比较糟糕。

我跟openvino对比了下,在同一台windows上,性能确实差一些,512*512输出。 ncnn openvino

EdVince commented 2 years ago

kpi+++++ 我想办法优化一下这个速度吧,现在确实是慢了点,体验比较糟糕。

我跟openvino对比了下,在同一台windows上,性能确实差一些,512*512输出。 ncnn openvino

你这CPU有点太慢了,建议换最新的CPU,小于8s不是问题

hubin858130 commented 2 years ago

kpi+++++ 我想办法优化一下这个速度吧,现在确实是慢了点,体验比较糟糕。

我跟openvino对比了下,在同一台windows上,性能确实差一些,512*512输出。 ncnn openvino

你这CPU有点太慢了,建议换最新的CPU,小于8s不是问题

害!还得再送一个月外卖, PWP2NCYHK$1{ 5B~{X3{`V2 应该就可以换新机器啦!

EdVince commented 1 year ago

更新了MHA版本的模型后,要支持动态shape是可以做的,但考虑到动态shape相比静态shape会缺少一些优化,导致内存和速度表现都不如静态shape的模型,所以暂时还是不考虑支持动态shape。

EdVince commented 1 year ago

目前已经支持了动态shape了,但仍然只有256x256和512x512的是有优化的,其他shape的没有优化,可能会慢一点。