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