我需要什么才能運行最先進的文本到圖像模型?游戲卡可以完成這項工作嗎?還是我應該買一個高級的 A100?如果我只有 CPU 怎么辦?
為了闡明這些問題,我們提出了不同 GPU 和 CPU 上Stable Diffusion的推理基準。以下是我們的發(fā)現(xiàn):
許多消費級 GPU 可以很好地完成這項工作,因為Stable Diffusion只需要大約 5 秒和 5 GB 的 VRAM 即可運行。
在輸出單張圖像的速度方面,最強大的 Ampere GPU(A100)僅比 3080 快 33%(或 1.85 秒)。
通過將批量大小推至最大值,A100 可以提供 2.5 倍的推理吞吐量(與 3080 相比)。
我們的基準測試使用文本提示作為輸入并輸出分辨率為 的圖像。我們使用Huggingface 擴散器庫中的模型實現(xiàn),并從速度、內(nèi)存消耗、吞吐量和輸出圖像質(zhì)量方面分析推理性能。我們研究了硬件(GPU 模型、GPU 與 CPU)和軟件(單精度與半精度、pytorch 與 onnxruntime)的不同選擇如何影響推理性能。
作為參考,我們將提供以下 GPU 設備的基準測試結果:A100 80GB PCIe、RTX3090、RTXA5500、RTXA6000、RTX3080、RTX8000。
最后但并非最不重要的一點是,我們很高興看到社區(qū)進展如此迅速。例如,“切片注意力”技巧可以進一步將 VRAM 成本降低到“低至 3.2 GB”,但推理速度會降低約 10%。我們也期待在不久的將來,一旦ONNX 運行時變得更加穩(wěn)定,就可以使用 CUDA 設備對其進行測試。
速度
下圖展示了使用不同的硬件和精度生成單幅圖像的推理速度,使用(任意)文本提示:“一張宇航員在火星上騎馬的照片”。
Stable Diffusion Text2Image 速度(以秒為單位)
我們發(fā)現(xiàn):
在我們測試的 Ampere GPU 上,生成單個輸出圖像的時間范圍3.74為5.59幾秒,包括消費者 3080 卡到旗艦 A100 80GB 卡。
半精度可40%將安培 GPU 的時間減少約,將52%上一代RTX8000GPU 的時間減少約。
我們認為,由于使用了 ,Ampere GPU 的加速比半精度的“較小” TF32。對于不熟悉 的讀者,它是一種格式,已被用作主要深度學習框架(如 PyTorch 和 TensorFlow)上 Ampere GPU 的默認單精度數(shù)據(jù)類型。由于它是一種真正的格式,因此可以預期半精度的加速比會更大。
我們在 CPU 設備上運行相同的推理作業(yè),以便了解在 GPU 設備上觀察到的性能。
Stable Diffusion Text2Image GPU 與 CPU
我們注意到:
GPU 的速度明顯更快——根據(jù)精度,速度可提高一到兩個數(shù)量級。
onnxruntime可以將 CPU 推理時間減少約40%到50%,具體取決于 CPU 的類型。
順便提一下,ONNX 運行時目前沒有針對 Hugging Face 擴散器的穩(wěn)定CUDA 后端支持,我們在初步測試中也沒有觀察到有意義的加速。我們期待在 ONNX 運行時針對Stable Diffusion進行進一步優(yōu)化后進行更全面的基準測試。
內(nèi)存
我們還測量了運行Stable Diffusion推理的內(nèi)存消耗。
Stable Diffusion Text2Image 內(nèi)存 (GB)
經(jīng)觀察,所有經(jīng)過測試的 GPU 的內(nèi)存使用情況都是一致的:
7.7 GB運行批量大小為 1 的單精度推理大約需要GPU 內(nèi)存。
4.5 GB運行批量大小為 1 的半精度推理大約需要GPU 內(nèi)存。
吞吐量
到目前為止,我們已經(jīng)測量了單個輸入的處理速度,這對于不能容忍哪怕是最小延遲的在線應用程序來說至關重要。但是,一些(離線)應用程序可能會關注“吞吐量”,它衡量在固定時間內(nèi)處理的數(shù)據(jù)總量。
我們的吞吐量基準測試將每個 GPU 的批處理大小推至最大值,并測量它們每分鐘可以處理的圖像數(shù)量。最大化批處理大小的原因是讓張量核心保持繁忙,以便計算可以主導工作負載,避免任何非計算瓶頸并最大化吞吐量。
我們在 pytorch 中以半精度運行了一系列吞吐量實驗,并使用了每個 GPU 可以使用的最大批量大?。?/p>
Stable Diffusion文本到圖像吞吐量(圖像/分鐘)
我們注意到:
再次,A100 80GB 表現(xiàn)最佳,且具有最高的吞吐量。
A100 80GB 與其他卡在吞吐量方面的差距可以通過此卡上可使用的最大批量大小較大來解釋。
作為一個具體的例子,下圖顯示了當我們將批處理大小從 1 更改為 28(不會導致內(nèi)存不足錯誤的最大值)時,A100 80GB 的吞吐量如何增加。同樣有趣的是,當批處理大小達到某個值時,吞吐量的增長并不是線性的,而是趨于平穩(wěn),此時 GPU 上的張量核心已飽和,GPU 內(nèi)存中的任何新數(shù)據(jù)都必須排隊才能獲得自己的計算資源。
Stable Diffusion Text2Image 批次大小與吞吐量(圖像/分鐘)
自動播報
Hugging Face 團隊對其擴散器代碼進行的更新聲稱,刪除自動投射可將 pytorch 的半精度推理速度提高約 25%。
使用自動播報:
with autocast("cuda"):
image = pipe(prompt).images[0]
未使用自動施放:
image = pipe(prompt).images[0]
我們在 NVIDIA RTX A6000 上重現(xiàn)了該實驗,并能夠驗證速度和內(nèi)存使用方面的性能提升。我們預計其他支持半精度的設備也會有類似的改進。
Stable Diffusion-text2image-pytorch-半精度速度
Stable Diffusion-text2image-pytorch-半精度內(nèi)存
綜上所述,請勿將 autocast 與 FP16 結合使用。
精確
我們很好奇半精度是否會降低輸出圖像的質(zhì)量。為了測試這一點,我們修復了文本提示以及“潛在”輸入,并將它們輸入到單精度模型和半精度模型中。我們以增加的步數(shù)運行了 100 次推理。每次運行時,都會保存兩個模型的輸出及其差異圖。
100 步中的單精度與半精度
我們的觀察是,單精度輸出和半精度輸出之間確實存在明顯差異,尤其是在早期步驟中。差異通常會隨著步驟數(shù)量的增加而減小,但可能不會消失。
有趣的是,這種差異可能并不意味著半精度輸出中存在偽影。例如,在步驟 70 中,下圖顯示半精度沒有在單精度輸出中產(chǎn)生偽影(額外的前腿):
單精度 v 半精度,步驟 70
重復實驗
您可以使用捷智算平臺自帶的存儲庫來重現(xiàn)本文中呈現(xiàn)的結果。
設置
在運行基準測試之前,請確保您已完成存儲庫安裝步驟。
然后您需要設置 huggingface 訪問令牌:
1、在 Hugging Face 上創(chuàng)建用戶賬戶并生成訪問令牌。
2、將您的 huggingface 訪問令牌設置為ACCESS_TOKEN環(huán)境變量:
export ACCESS_TOKEN=<hf_...>
用法
啟動benchmark.py腳本以將基準測試結果附加到現(xiàn)有的 benchmark.csv 結果文件:
python ./scripts/benchmark.py
啟動benchmark_quality.py腳本來比較單精度和半精度模型的輸出:
python ./scripts/benchmark_quality.py
備注
由于每次運行的文本提示以及“潛在”輸入都是固定的,這相當于運行 100 步推理,并保存每一步的中間結果。