使用 Transformers 優(yōu)化文本轉(zhuǎn)語音模型 Bark

?? Transformers 提供了許多最新最先進(jìn) (state-of-the-art, SoTA) 的模型,這些模型橫跨多個領(lǐng)域及任務(wù)。為了使這些模型能以最佳性能運行,我們需要優(yōu)化其推理速度及內(nèi)存使用。
?? Hugging Face 生態(tài)系統(tǒng)為滿足上述需求提供了現(xiàn)成且易于使用的優(yōu)化工具,這些工具可應(yīng)用于庫中的所有模型。用戶只需添加幾行代碼就可以輕松?減少內(nèi)存占用?并?提高推理速度。
在本實戰(zhàn)教程中,我將演示如何用三個簡單的優(yōu)化技巧來優(yōu)化 Bark 模型。Bark 是?? Transformers 支持的一個文本轉(zhuǎn)語音 (Text-To-Speech, TTS) 模型。所有優(yōu)化僅依賴于 Transformers、Optimum 以及 Accelerate 這三個 ?? 生態(tài)系統(tǒng)庫。
本教程還演示了如何對模型及其不同的優(yōu)化方案進(jìn)行性能基準(zhǔn)測試。
本文對應(yīng)的 Google Colab 在:https://colab.research.google.com/github/ylacombe/notebooks/blob/main/Benchmark_Bark_HuggingFace.ipynb
本文結(jié)構(gòu)如下:
目錄
Bark 模型簡介
不同優(yōu)化技巧及其優(yōu)點概述
基準(zhǔn)測試結(jié)果展示
Bark 模型架構(gòu)
Bark?是 Suno AI 提出的基于 transformer 的 TTS 模型,其原始代碼庫為 suno-ai/bark。該模型能夠生成各種音頻輸出,包括語音、音樂、背景噪音以及簡單的音效。此外,它還可以產(chǎn)生非語言語音,如笑聲、嘆息聲和抽泣聲等。
自 v4.31.0 起,Bark 已集成入 ?? Transformers!
你可以通過 這個 notebook 試試 Bark 并探索其功能。
Bark 主要由 4 個模型組成:
BarkSemanticModel
?(也稱為?文本?模型): 一個因果自回歸 transformer 模型,其輸入為分詞后的詞元序列,并輸出能捕獲文義的語義詞元。BarkCoarseModel
?(也稱為?粗聲學(xué)?模型): 一個因果自回歸 transformer 模型,其接收?BarkSemanticModel
?模型的輸出,并據(jù)此預(yù)測 EnCodec 所需的前兩個音頻碼本。BarkFineModel
?(也稱為?細(xì)聲學(xué)?模型),這次是個非因果自編碼器 transformer 模型,它對?先前碼本的嵌入和?進(jìn)行迭代,從而生成最后一個碼本。在?
EncodecModel
?的編碼器部分預(yù)測出所有碼本通道后,Bark 繼續(xù)用其解碼器來解碼并輸出音頻序列。
截至本文撰寫時,共有兩個 Bark checkpoint 可用,其中一個是 小版,一個是 大版。
加載模型及其處理器
預(yù)訓(xùn)練的 Bark 小 checkpoint 和 大 checkpoint 均可從 Hugging Face Hub 上加載。你可根據(jù)實際需要加載相應(yīng)的 repo-id。
為了使實驗運行起來快點,我們默認(rèn)使用小 checkpoint,即?“suno/bark-small”
?。但你可以隨意改成?“suno/bark”
?來嘗試大 checkpoint。
將模型放到加速器上以優(yōu)化其速度:
加載處理器,它主要處理分詞以及說話人嵌入 (若有)。
優(yōu)化技巧
本節(jié),我們將探索如何使用 ?? Optimum 和 ?? Accelerate 庫中的現(xiàn)成功能來以最少的代碼改動達(dá)到優(yōu)化 Bark 模型的目的。
設(shè)置實驗環(huán)境
首先,我們準(zhǔn)備一個輸入文本并定義一個函數(shù)來測量 Bark 生成過程的延遲及其 GPU 顯存占用情況。
測量延遲和 GPU 內(nèi)存占用需要使用特定的 CUDA 函數(shù)。我們實現(xiàn)了一個工具函數(shù),用于測量模型的推理延遲及 GPU 內(nèi)存占用。為了確保結(jié)果的準(zhǔn)確性,每次測量我們會運行?nb_loops
?次求均值:
基線
在優(yōu)化之前,我們先測量下模型的基線性能并聽一下生成的音頻,我們測量五次并求均值:
輸出:
現(xiàn)在,我們可以播放一下輸出音頻:
重要說明
上例中運行次數(shù)較少。為了測量和后續(xù)對比的準(zhǔn)確性,運行次數(shù)需要增加到至少 100。
增加?nb_loops
?一個主要原因是,同一輸入的多次運行所生成的語音長度差異也很大。因此當(dāng)運行次數(shù)較少時,有可能通過?measure_latency_and_memory_use
?測出的延遲并不能反映出優(yōu)化方法的實際性能!文末的基準(zhǔn)測試取的是 100 次運行的均值,用以逼近模型的真實性能。
1. ?? Better Transformer
Better Transformer 是 ??? Optimum 的一個功能,它可以幫助在后臺執(zhí)行算子融合。這意味著模型的某些操作在 GPU 上的性能將會得到進(jìn)一步優(yōu)化,從而加速模型的最終運行速度。
再具體一點,?? Transformers 支持的大多數(shù)模型都依賴于注意力,這使得模型在生成輸出時可以選擇性地關(guān)注輸入的某些部分,因而能夠有效地處理遠(yuǎn)程依賴關(guān)系并捕獲數(shù)據(jù)中復(fù)雜的上下文關(guān)系。
Dao 等人于 2022 年提出了一項名為 Flash Attention 的技術(shù),極大地優(yōu)化了樸素注意力的性能。
Flash Attention 是一種更快、更高效的注意力算法,它巧妙地結(jié)合了一些傳統(tǒng)方法 (如平鋪和重計算),以最大限度地減少內(nèi)存使用并提高速度。與之前的算法不同,F(xiàn)lash Attention 將內(nèi)存使用量從與序列長度呈平方關(guān)系降低到線性關(guān)系,這對關(guān)注內(nèi)存效率的應(yīng)用尤其重要。
?? Better Transformer 可以開箱即用地支持 Flash Attention!只需一行代碼即可將模型導(dǎo)出到 ?? Better Transformer 并啟用 Flash Attention:
輸出:
利弊
效果不會下降,這意味著你可以獲得與基線版本完全相同的結(jié)果,同時提速 20% 到 30%!想要了解更多有關(guān) Better Transformer 的詳細(xì)信息,請參閱此 博文。
2. 半精度
大多數(shù)人工智能模型通常使用稱為單精度浮點的存儲格式,即?fp32
?,這在實踐中意味著每個數(shù)都用 32 比特來存儲。
你也可以選擇使用 16 比特對每個數(shù)進(jìn)行編碼,即所謂的半精度浮點,即?fp16
?(譯者注: 或?bf16
?),這時每個數(shù)占用的存儲空間就變成了原來的一半!除此以外,你還可以獲得計算上的加速!
但天下沒有免費的午餐,半精度會帶來較小的效果下降,因為模型內(nèi)部的操作不如?fp32
?精確了。
你可以通過簡單地在?BarkModel.from_pretrained(...)
?的入?yún)⒅刑砑?torch_dtype=torch.float16
?來將 Transformers 模型加載為半精度!
代碼如下:
輸出:
利弊
雖然效果略有下降,但內(nèi)存占用量減少了 50%,速度提高了 5%。
3. CPU 卸載
正如本文第一部分所述,Bark 包含 4 個子模型,這些子模型在音頻生成過程中按序調(diào)用。換句話說,當(dāng)一個子模型正在使用時,其他子模型處于空閑狀態(tài)。
為什么要討論這個問題呢?因為 GPU 顯存在 AI 工作負(fù)載中非常寶貴,顯存中的運算速度是最快的,而很多情況下顯存不足是推理速度的瓶頸。
一個簡單的解決方案是將空閑子模型從 GPU 顯存中卸載至 CPU 內(nèi)存,該操作稱為 CPU 卸載。
好消息: ?Bark 的 CPU 卸載已集成至 ?? Transformers 中,只需一行代碼即可使能。唯一條件是,僅需確保安裝了 ?? Accelerate 即可!
輸出:
利弊
速度略有下降 (10%),換得內(nèi)存占用的巨大降低 (60% ??)。
啟用此功能后,?bark-large
?占用空間從原先的 5GB 降至 2GB,與?bark-small
?的內(nèi)存占用相同!
如果你還想要降更多的話,可以試試啟用?fp16
?,內(nèi)存占用甚至可以降至 1GB。具體可以參見下一節(jié)的數(shù)據(jù)。
4. 組合優(yōu)化
我們把上述所有優(yōu)化組合到一起,這意味著你可以合并 CPU 卸載、半精度以及 ?? Better Transformer 帶來的收益!
輸出:
利弊
最終,你將獲得 23% 的加速并節(jié)約 80% 的內(nèi)存!
批處理
得隴望蜀?
加個批處理吧,上述 3 種優(yōu)化技巧加上批處理可以進(jìn)一步提升速度。批處理即將多個樣本組合起來一起推理,這樣會使這些樣本的總生成時間低于逐樣本生成時的總生成時間。
下面給出了一個批處理的簡單代碼:
基準(zhǔn)測試結(jié)果
上文我們進(jìn)行的這些小實驗更多是想法驗證,我們需要將其擴展以更準(zhǔn)確地衡量性能。另外,在每次正式測量性能之前,還需要先跑幾輪以預(yù)熱 GPU。
以下是擴展至 100 個樣本的基準(zhǔn)測量的結(jié)果,使用的模型為?大 Bark。
該基準(zhǔn)測試在 NVIDIA TITAN RTX 24GB 上運行,最大詞元數(shù)為 256。
如何解讀結(jié)果?
延遲
該指標(biāo)主要測量每次調(diào)用生成函數(shù)的平均時間,無論 batch size 如何。
換句話說,它等于?。
延遲越小越好。
最大內(nèi)存占用
它主要測量生成函數(shù)在每次調(diào)用期間使用的最大內(nèi)存。
內(nèi)存占用越小越好。
吞吐量
它測量每秒生成的樣本數(shù)。這次,batch size 的因素已被考慮在內(nèi)。
換句話說,它等于?。
吞吐量越高越好。
單樣本推理
下表為?batch_size=1
?的結(jié)果。

不出所料,CPU 卸載極大地減少了內(nèi)存占用,同時略微增加了延遲。
然而,結(jié)合 bettertransformer 和?fp16
?,我們得到了兩全其美的效果,巨大的延遲和內(nèi)存降低!
batch size 為 8
以下是?batch_size=8
?時的吞吐量基準(zhǔn)測試結(jié)果。
請注意,由于?bettertransformer
?是一種免費優(yōu)化,它執(zhí)行與非優(yōu)化模型完全相同的操作并具有相同的內(nèi)存占用,同時速度更快,因此所有的基準(zhǔn)測試均?默認(rèn)開啟此優(yōu)化。

這里,我們看到了組合所有三個優(yōu)化技巧后的性能潛力!
fp16
?對延遲的影響在?batch_size = 1
?時不太明顯,但在?batch_size = 1
?時的表現(xiàn)非常有趣,它可以將延遲減少近一半,吞吐量幾乎翻倍!
結(jié)束語
本文展示了 ?? 生態(tài)系統(tǒng)中的一些現(xiàn)成的、簡單的優(yōu)化技巧。使用這些技巧中的任何一種或全部三種都可以極大地改善 Bark 的推理速度和內(nèi)存占用。
使用?? Better Transformer 和 CPU 卸載,你可以對大 Bark 模型進(jìn)行推理,而不會出現(xiàn)任何性能下降,占用空間僅為 2GB (而不是 5GB),同時速度提高 15%。
如果你鐘情于高吞吐,可以?把 batch size 打到 8,并利用 ?? Better Transformer 和 fp16。
如果你“既要,又要,還要”,試試?fp16、?? Better Transformer 加 CPU 卸載?組合優(yōu)化吧!
英文原文:?https://hf.co/blog/optimizing-bark
原文作者: Yoach Lacombe
譯者: Matrix Yao (姚偉峰),英特爾深度學(xué)習(xí)工程師,工作方向為 transformer-family 模型在各模態(tài)數(shù)據(jù)上的應(yīng)用及大規(guī)模模型的訓(xùn)練推理。
審校/排版: zhongdongy (阿東)