Quantcast
Channel: Hiraku Dev
Viewing all articles
Browse latest Browse all 241

在 Mac 玩 Core ML Stable Diffusion 的小心得

$
0
0

原本想寫一篇如何在 Apple Silicon 的 Mac 玩 Core ML Stable Diffusion 的文章,後來發現原本文件已經很清楚了,所以覺得應該不用再贅述,改成寫一些使用的心得,還有一些小技巧好了。

先講重點:雖然 Apple 在 GitHub 上面寫跟我同規格的 M1 Ultra 48 GPU 版本可以 13 秒跑出結果,但是我實測是測不出來的,再怎樣跑最快也就是 30 秒左右,不知道是我少了什麼步驟還是 Apple 用了什麼黑魔法沒放出來。

雖然如此,我還是有測了一下,然後整理了一些小技巧,可以讓執行速度快一點,也可以讓大家少走點彎路。

以下測試環境:

  • macOS 13.1 Beta 4(22C5059b)
  • Mac Studio(M1 Ultra 20 CPU,48 GPU,64GB RAM)
  • Stable Diffusion v1.4
  • Prompt 固定為 “a high quality photo of an astronaut riding a horse in space”
  • Seed 固定使用 13

 

在最新的 macOS 13.1 beta4 以上執行

雖然 macOS 13.0.1 也可以執行,但是 Apple 有在 macOS 13.1 對 Stable Difussion 做最佳化。更重要的是在 macOS 13.0.1 是無法呼叫 GPU 的,生成的圖片會變成一整片灰色。只能給 CPU 跟 Apple 的神經網路引擎(Apple’s Neural Engine,縮寫為 ANE)使用,效能差很多。

 

使用轉換好的 Checkpoints

不要浪費時間按照原本 GitHub 上面的教學手動轉換 model,因為需要很長的時間跟大量記憶體(在 M1 Ultra 我轉換 Stable Diffusion 2 Base 花了半小時以上,用了 40GB RAM),可以在這邊下載已經轉換好的 checkpoint。

可用的預先轉換 checkpoint 包含:

  • Stable Diffusion v1.4
  • Stable Diffusion v1.5
  • Stable Diffusion v2 base

下載需要 git-lfs,要另外用 homebrew 安裝。

 

下載完成之後會看到 original 跟 split_einsum 兩個版本,original 是 CPU 跟 GPU 用的,split_einsum 則可以給 ANE 使用。

每個資料夾底下又分為 packages 跟 compiled,packages 是給 python 用的,compiled 是給 swift 用的。

有些 model 會有 unet.mlpackage、unet_chunk1.mlpackage、unet_chunk2.mlpackage 三個檔案,在電腦上我們不需要把檔案分割以減少資源消耗,所以可以直接砍掉 unet_chunk1、unet_chunk2 減少佔用空間。

即使使用轉換好的 checkpoint,第一次使用的時候還是會先下載一堆東西,這是正常的。

 

Swift 的版本通常比較快

雖然原始文件寫用 Python,但是我自己測試用 Swift 因為少了一些轉換過程,所以跑起來比較快。

以下是一些測試結果,都是用預先轉換的 Stable Diffusion v1.4 checkpoint,包含模型載入時間,都是用 CPU 和 GPU 運算(測試發現在 Mac 上面用 ANE 反而拖慢速度)

  • original + python: 51s
  • original + swift: 42s
  • split_einsum + python: 43s
  • split_einsum + swift: 28s

可以看到,用 Swift 版本快了約 10 秒,用 split_einsum 又比 original 快 10 秒。我還真不知道原始表格為何寫用 original + python 可以在我這台機器跑出 13 秒的成績,有人知道的話歡迎告訴我。

 

關閉 Safety Checker 來加速

在 Apple 提供的程式碼裡面,預設是開啟 Safety Checker 的,這個東西可以防止使用者產生一些 NSFW 的內容。請注意,關閉 Safety Checker 僅是為了加速圖片繪製使用,請勿濫用這個功能。

Python 版本,請修改 pipeline.py,在 463 行左右新增下面最下面兩行內容:

def main(args):
    logger.info(f"Setting random seed to {args.seed}")
    np.random.seed(args.seed)

    logger.info("Initializing PyTorch pipe for reference configuration")
    from diffusers import StableDiffusionPipeline
    pytorch_pipe = StableDiffusionPipeline.from_pretrained(args.model_version,
                                                           use_auth_token=True)
    pytorch_pipe.requires_safety_checker = False
    pytorch_pipe.safety_checker = None
...

 

Swift 版本啥都不用改,直接用 --disable-safety 指令就好了。

實測 Python 版本會快 4 秒鐘左右,因為 Python 版本會少載入一個 model,Swift 因為 model 都是預先編譯好的,所以加速比較不明顯,只快了 1 秒左右。

關掉 Safety Checker 之後,可以刪除 python 用的 safety_checker.mlpackage 檔案,節省空間。

部分 model 內建 safety checker,例如 Stable Diffusion v2 會忽略 NSFW 的 prompt,所以這招對它沒用。

 

隨機種子

--seed ${RANDOM} 指令會使用隨機種子,不必每次都在那邊調種子數字。

 

不同運算單元畫出的成果不同

即使使用同一個 seed 跟 prompt,用 GPU 跟 ANE 繪圖出來的結果會構圖接近,但是不同。

舉個例子,左邊用 CPU 跟 ANE,右邊用 CPU 跟 GPU:

 

最後

不用我說,你也知道,封面圖就是用 AI 畫出來的。

 

參考文章:Using Stable Diffusion with Core ML on Apple Silicon (huggingface.co)


Viewing all articles
Browse latest Browse all 241

Trending Articles