
近年來,行業內不斷湧現各種十億,百億,千億級別的大模型,在各個領域均展現了強大的能力。而智慧手機作為擁有最大使用者數量的終端裝置,正成為大模型實現個性化場景與服務的核心載體。然而想在移動端有限的硬體資源上部署引數量龐大的大模型,其效能,記憶體,功耗均面臨著嚴峻的挑戰。
我是來自 vivo AI 研究院的章蘇遲,當前在 vivo AI 研究院負責大模型的在端側的部署與業務落地。今天非常榮幸能在這裡同大家分享我們 vivo 在端側大模型端側化過程中的解決方案與思考。
大家這幾年買手機的時候,經常會聽到一個概念叫做 AI 手機,相信大家對 AI 手機這個詞已經不陌生了。
傳統上,雖然智慧手機有形形色色的 AI 功能,但實際上很多人在用的時候都會感到一些困惑,就是這些所謂的 AI 功能都是單點的,它並沒有與系統有很好的結合,而且所謂的智慧化 AI 體驗,聽起來好像也沒法理解使用者的意圖。
所以 AI 手機實際用起來,大家最後的感受就是並沒有那麼智慧,這也是以往 AI 手機的痛點。
隨著大模型技術的發展,尤其是這幾年多模態大模型不斷湧現,它在各個專業領域都展現出了驚人的能力。行業正從傳統的 AI 時代全面邁向大模型 AI 時代。

面對這種行業變革,我們也產生了一個想法就是,如果我們能把大模型技術與手機結合,那麼勢必能給使用者帶來更加智慧、個性化的服務,全面重塑手機體驗。
在手機上應用大模型雲端大模型和端側大模型這兩種方案。雲端大模型不會受到手機有限計算資源的影響,它的能力非常強,發揮的空間也非常大,具備相當多的優勢。
但手機上還有非常多的與隱私相關的場景,比如說我們不能把一些使用者的隱私資料上傳到雲端,此時我們就只能選擇端側化的方案。但如果選用了端側化方案,就意味著我們要把端側大模型塞到手機裡,這聽起來就有點不可思議,這真的能實現嗎?
我們回溯一下這幾年大模型演算法的發展趨勢,可以發現大模型的知識密度是在持續增強的。對於同等能力的模型,它的引數量隨時間推移是呈快速下降的趨勢。
比如說我們現在自研的 vivo 藍心大模型,3B 大模型在演算法能力上已經能夠比肩以往的 10B 甚至幾十 B 的模型,所以大模型的小型化已經成為了一種趨勢,與我們將大模型落地到端側這個訴求是正好匹配的。

我們 vivo 當前已經將大模型落地到端側,為使用者帶來了更加智慧和安全的體驗。這裡的安全指的是我們對使用者隱私資料的保護。
端側大模型在推理的過程中,它整個鏈路所有的資料都是純端處理的,所以使用者的任何隱私資訊都不會上雲,很好地保證了我們使用者的隱私保護需求。
至於個人智慧化的體驗,我們就來看看 vivo 把端側大模型運用在了哪些場景。當前我們把藍心大模型運用在了很多系統應用中。
第一個就是 vivo 輸入法,這是小 V 寫作的功能,它主要用到了大模型的文案生成與潤色能力,比如說大家在寫購物評價,又或者同朋友聊天,它能幫你一鍵生成指定的文案和一些高情商的回覆。
第二個是我們電話助手的通話摘要功能,它主要用到了藍心大模型的總結摘要能力,它可以幫使用者生成通話內容,比如說你同你的老闆打了工作電話,它可以幫你總結整通電話,生成待辦事項。
第三個是我們藍心小 V 裡的文字總結功能,它可以幫助你自動總結文件的主題摘要。你不需要看整篇文件,它可以幫你快速生成幾百字的摘要,幫助使用者快速瞭解文章要領。
最後一個功能就是我們錄音機裡的智慧命名功能,它可以幫助使用者自動識別錄音檔案內容,自動生成對應的檔名,這樣可以避免使用者為了找錄音檔案而反覆聽,可以省很多時間。

以上所有場景都是透過 vivo 端側大模型實現的。
大家都說大模型落地到端側非常難,首先我們要明白它到底難在哪裡,最關鍵在於模型的引數量與效能指標之間的平衡。手機端的硬體資源是非常有限的,晶片算力有限,記憶體大小也有限,手機的功耗也是非常重要的指標。模型引數量越大,就意味著它消耗的計算量越大,它對頻寬的需求也越高,功耗也就越高。
所以如何平衡模型效果與手機上的這些體驗指標,是非常大的問題。如果我們把模型引數量選的非常大,那麼它計算量就很高,它直接帶來的問題就是速度非常慢,使用者體驗的延遲就會非常久。
另外也帶來一個問題,就是記憶體佔用會非常大,進而導致系統的流暢性會受到一些影響,功耗隨之升高,導致我們手機掉電非常快,發熱也非常嚴重,這些都是我們端側化非常棘手的問題。

在識別到我們端側的瓶頸之後,就要用技術指標量化它。這裡的執行記憶體就是大模型在執行過程中對記憶體的佔用,功耗是執行過程中的電流或耗電量,但大模型的效能指標我們又怎樣衡量?
為了拆解清楚這個問題,我們先來簡單回顧一下大模型的推理過程。

我們給大模型輸入 prompt,然後它就預測出一段簡單的話。這個簡單的過程主要拆分為三個階段,首先是大模型的初始化載入階段,在這個階段模型就要從 flash 儲存讀取到我們 DRAM 中。
後面的推理又拆分為兩個階段,首先是 prompt 輸入大模型,然後大模型預測出第一個詞,這個過程我們稱為 prefill,也就是首詞。在輸出第一個 token 後,我們還要把 token 送回大模型,然後讓大模型不斷預測下一個詞,這個過程是連續出詞的過程,我們把它稱為 decode。
所以大模型的推理效能指標主要有兩個,也就是 prefill 效能和 decode 效能,我們在後續的測試以及最佳化過程中,需要同時關注這兩個指標才行。
我們明白了用什麼技術指標來量化大模型效能後,很快就對大模型進行了一次端測效能摸底,來看一下它在手機端的表現是怎樣的。

這裡選取的是我們藍心的 7B 模型,在天機 9300CPU 上執行。我們開了 6 個執行緒,來看一下我們後面的效能指標。首先是 prefill 效能和 decode 效能都是 10 多個每秒多一點。
這裡要說明一下 prefill 效能和 decode 的效能是怎樣計算的。prefill 效能代表的是大模型處理輸入 token 的能力,計算方式就是把輸入的 prompt 數除以 prefill 過程的總耗時,比如說 19.7 token 每秒,就意味著它每秒能處理 19.7 個輸入 token。輸出 token 的計算方式就是把輸出的 token 數除以它 decode 流程的總耗時,這裡的 10.9 token 每秒就意味著它每秒能出 10.9 個 token。
再來看一下這組資料,首先是出詞效能 10.9 token 每秒,換算成中文漢字大概是 14~16 字每秒,這個效能還是能滿足人眼閱讀的基礎體驗的,沒有問題。但這個 prefill 效能在最佳化之前,我們發現它只有 19.7 token 每秒,這裡的問題就非常大了。
設想一個文件總結的功能場景,我的文章假設輸入有 1000 個 token,並不長,可能也就是 1400~1600 個漢字左右,可能有些文件比這個還長。如果是這樣一篇文件輸入到大模型,它的 prefill 耗時要多久?要 50 多秒,意味著使用者總結這個文件時,需要等待 50 多秒才能出第一個詞,這是絕對無法滿足體驗的,所以這塊是我們亟需最佳化的指標。
功耗我們這裡測出來是兩點幾安,而過載遊戲的功耗峰值也就在一安左右,所以說功耗是非常可怕的,這對我們手機的續航和發熱都有著嚴重的影響。最後便是記憶體了,實測下來 7B 模型的記憶體佔用在 3.6GB 左右,大家知道現在主流手機的記憶體大概在 12GB 或 16GB 這樣的規格,所以我們在端測如何選擇模型的引數量,也是亟需解決的問題。
經過一次初步摸底後,我們就知道了大模型在手機端的效能指標是怎樣了,接下來我們就從效能、功耗以及體積和記憶體來全面講解一下,我們端側大模型是怎樣去做的。
首先是體積和記憶體的最佳化。在做最佳化之前,我們要確定端測到底適合用多大的模型,到底用什麼指標,什麼標準去選擇?我們認為核心決定因素是我們機型的剩餘記憶體和效能。前面說過我們 7B 的效能能達到 10 token 每秒左右,效能已經能夠滿足一些閱讀場景的基礎體驗了。
所以在手機端上選擇模型時,可以認為小於等於 7B 是比較合理的區間。再結合我們手機的剩餘記憶體,我們現在主流旗艦機型的剩餘記憶體在 12GB 左右,從這個標準再結合大模型的記憶體開銷來畫一條線。

我們認為 12GB 機型的綜合最佳選擇是 3B 模型,3B 是我們端側化比較合理的尺寸。在選定模型尺寸後,我們基於模型進行了一些輕量化處理,這裡主要從權重量化以及 attention 最佳化兩個方面展開。
首先是 attention 結構,我們最原始的藍心 3B 模型採用 MHA 結構,也就是說它每個 query 的頭對應的 key 和 value 矩陣都是不共享的。在這種情況下 key 和 value 矩陣的引數量就會非常龐大,這裡就有一點問題。
我們全面測試過它的效能與效果後,採用了 GQA 這種結構,將 query 分成多組,每組共享同一個 key 和 value 矩陣。
之後就是權重量化對比浮點推理,我們採用更低位元的 4bit 的權重量化,搭配 int16 的 activation,這樣對比原始的 FP16 的權重,模型體積就能降為原來的 1/4。另外我們針對 kv cache 也採用了 int8 量化,這樣 kv cache 的記憶體佔用也能進一步壓縮。

經過這兩種方式的輕量化後,首先模型權重的體積從 5.7GB 下降到了 1.27GB,有非常大的最佳化。另外值得注意的就是 kv cahce 的記憶體佔用從每 1k 160M 降低到了 32M,也是有意義的。
這就意味著我們在端側採用更長長度的 kv cahce,它的記憶體增量就不會那麼大了。所以我們在端側採用比如說 2k 或 4k 這種長度的上下文,它的記憶體影響就相對小很多。以上就是我們記憶體和體積的最佳化方案。
效能和功耗最佳化是我們整個端側化過程中的重中之重。做過手機端 AI 推理最佳化的同行應該知曉,手機 SOC 針對 AI 場景專門搭載了用於神經網路加速的 NPU 晶片,對比傳統的 CPU 和 GPU,NPU 有著更高的算力和更好的能效,在推理方面有著非常大的優勢。
因此我們很多從業者在做端側化最佳化的過程中,遇到這種要最佳化效能和功耗的問題,他就會脫口而出,不要用 CPU 和 GPU 了,我們去 NPU 算一下,這句話在大部分的場景都是正確的。但我們仍然要拆解清楚,針對具體的計算任務,NPU 到底是怎樣發揮優勢的?是不是針對任何任務,NPU 都有全方位的優勢呢?

為了分析這個問題,我們先對大模型的計算任務進行了分析和拆解。由於我們 prefill 的輸入是完整的 prompt,它經過 embedding 的運算元後變成了多維矩陣,這個多維矩陣在後面會同 QKV 以及 MLP 裡的這些矩陣引數進行運算,因此整個 prefill 過程的計算任務本質是矩陣乘法。
而 decode 的過程則不一樣,decode 過程輸入的是 token,token 經過 embedding 的運算元處理後變成了一維向量,一維向量和後續的 QKV 以及 MLP 的 FC 進行計算後,實際上它的計算任務是矩陣向量乘法。所以 decode 過程和 prefill 過程的計算任務是有本質區別的。
接下來我們就根據這兩種計算任務來實際看一下 NPU 在這兩種任務上的表現究竟是怎樣的。矩陣乘法是典型的計算密集型任務,它的效能同器件的算力是直接相關的。
我們簡單回顧一下矩陣乘法的計算過程,比如說簡單的 A 矩陣乘 B 矩陣得到 C 矩陣,如圖所示 A 矩陣的 A0 到 A3 這一行,乘上 B 矩陣的 B0~B3 這一列,它得到的是 c0 這一個數。同理 c1、c2、c3 就是 a0 到 a3 乘上 B 矩陣的後面幾列。

如果我們不做任何最佳化,推導一下這個過程不難發現, A 矩陣和 B 矩陣裡面有大量資料是重複訪問的。這時候就會引出問題,就是整個矩陣運算過程中的訪存效率非常低下,無論是 A 矩陣還是 B 矩陣都有非常大量的重複資料訪問。
那麼怎樣去做矩陣乘法最佳化,最通用的策略就是對 A 矩陣和 B 矩陣進行分 tile 了,比如說我們在 CPU 上做矩陣,以 ARM 架構為例,我們通常會把這個矩陣分成 4×4 的 tile,然後把這些 tile 的資料依次落到 ARM 計算器中。
這時以我們 4×4 的 tile 去劃分的話,最終我們會發現 A 矩陣和 B 矩陣的訪存次數都會變為原來的 1/4。用技術指標去衡量的話,就是 A 矩陣的複用係數變為 4,B 矩陣的複用係數也是 4,這是分 tile 帶來的最佳化。
經過這種方式最佳化,矩陣乘計算過程中 A 矩陣和 B 矩陣的訪存量大幅度下降,整個矩陣計算的耗時會大幅度縮短。
這時候大家就想到一個問題,既然複用係數變為 4,效能有那麼大的最佳化,我們能不能讓複用係數更高一些,比如說 8 或者 16 甚至 32,這樣效能不是會更快嗎?但對不起,CPU 做不到這一點。我們就以 ARM64 架構的 CPU 為例,它的標準向量暫存器只有 32 個,而且每一個暫存器只有 128bit 的位寬,所以在計算矩陣生成的過程中,把複用係數提升到 4 時,你就會發現它的計算器差不多就要用完了。
你想再把複用係數往上提,會出現暫存器不夠用的問題。這也是為什麼 CPU 在算矩陣乘時,對比 GPU,NPU 這種專門處理矩陣乘法的硬體沒有優勢的原因。
那麼 NPU 又是如何呢?NPU 內部的整個 MAC 陣列是非常龐大的,有 2D 甚至是 3D 的,它的高算力優勢非常明顯,因此計算矩陣乘過程中,可以把一次性把大量資料搬到它的整個 MAC 陣列中一次計算完,所以它的矩陣乘的複用係數是遠大於 4 的。
這裡用一張表來綜合對比 CPU 和 NPU 的引數區別。首先以天機 9400 CPU 為例,它只有 32 個向量暫存器,每個只有 128bit 位寬,總體來說它的 INT8 算力,我們把超大核和大核全部加起來也就 2Tops 左右。
NPU 配備大規模矩陣運算單元,它的總算力早已超過了幾十 Tops,所以在矩陣乘任務上, NPU 對比 CPU 是有絕對效能優勢的。再加上 NPU 本身製程設計帶來的低功耗優勢,所以在整個 prefill 過程中,CPU 是沒法同 NPU 比的。

那麼 decode 階段又如何?前文提到 decode 階段做的是矩陣向量乘法,它和矩陣乘的最大區別就是 A 矩陣是一維向量。我們再看一下計算過程, A0 和 A3 和 B0 和 B3 的這一列做運算得到 c0。大家發現算完 c0 之後,B0~B3 這一列是不是就不參與計算了所以整個計算過程中它只被複用一次,意味著 B 的複用係數是一,是沒有辦法複用的。
無論你是用 CPU 算還是 NPU 算,這個複用係數是無法最佳化的。基於這個特性,我們代入 3B 的算力和訪存的資料估算一下。這裡以計算量為 5Gops 和訪存量為 1.5GB 來估算,最後算出來計算耗時大概在小於 5 毫秒的水平,訪存耗時在 30 毫秒水平。
透過指令的流水最佳化,計算耗時是可以被訪存耗時隱藏的,所以整個矩陣向量乘法的效能瓶頸在訪存。於是我們就可以意識到一個問題,就是 NPU 對比 CPU 在 decode 任務上是沒有明顯效能優勢的,但 NPU 對比 CPU 還是有著功耗的優勢。
綜上所述,雖然結論沒有變化,因為 prefill 過程 NPU 對比 CPU 還是有著很明顯的效能優勢,所以我們最終還是得用 NPU 去推理。
但對計算任務的分析也讓我們明白了,面對各種不同的計算任務時,它有著各自的優劣勢,以及我們有對應的效能分析方法,我們要理解其背後的原理,這樣對從業者來說還是非常重要的。
我們最終還是選擇了 NPU 去部署大模型,但事情沒有這麼順利,我們很快就遇到了最大的卡點,那就是 NPU 對動態 shape 的支援不好。

比如我們假設 NPU 固定了模型的輸出水平是 1000,但實際大模型輸入的 token 數是隨機的,可能這一次是 1000 個 token,下次是 1001 個 token。結果這 1000 個 token 是可以正常跑的,1001 個 token 是跑不了的。可如果只能接受一種長度的輸入的話,它肯定沒法滿足我們實際場景的需要。
NPU 的推理方案到底應該怎樣設計才能滿足我們所有動態輸入的場景?基於以前視覺推理的經驗,我們非常容易就想到,它既然不支援動態輸入的話,我們就把輸入切一下,把 prompt 切分成若干個等長的 patch 之後再送進去做推理。

我們本來還是覺得事情挺順利的,但馬上又遇到了第二個問題,那就是整個大模型的推理過程中,是否真的能按照這種切分 patch 的方式去做呢?也就是說我們把整個 prompt 切成多段去分別做 prefill,是否它整個計算過程在數學上同完整推理是等效的?
如果它這裡不等效,這麼切實際上是錯的,大模型可能得不到正確的結果,所以我們必須要證明這個過程的正確性。
為此我們去梳理一下大模型的結構,發現 QKV 的矩陣運算以及後面 MRP 的 FC 運算都是矩陣乘法,對這一部分的運算,prompt 無論是拆分還是整合是沒有影響的,因為它是具備空間獨立性的。唯一需要關注的就是 attention 結構中的 batchmatmul 和 maskinf 的計算。
為了理清楚這個問題,我們把 batchmatmul 的推理,全量推理以及分段推理的結果進行了視覺化輸出,如上圖所示。
這裡舉個例子,假設我們把 prompt 分為 4 個 patch 去推理,這 4 個 patch 的推理最終計算出來的部分就是如圖所示的正方形矩陣的左下角部分。
看到這個圖後,我們就馬上意識到一個問題,我們只算了左下角,右上角沒算會不會導致計算結果錯誤?
不是,因為大模型的整個彈性結構中,後面有個 maskinf 的計算。它存在的意義就是在於,因為大模型的每個 token 只能同前面的 token 產生 attention 的分佈,所以它要透過 mask 矩陣的運算,把右上三角的這個部分給遮蔽掉。
我們後來發現遮蔽掉的上三角部分正好是我們沒有計算的部分,所以說整個分 patch 過程中帶來的只計算區域性資料的問題,它對最後大模型的推理過程是沒有影響的。我們只計算下三角的部分,大模型最後的 prefill 計算還是正確的。
推匯出這個之後,大模型的分 patch 推理的正確性就證明完畢,意味著大模型的分 patch 推理方案是成立的,可以放心往下走。這裡順著再說一句,因為這個 batchmatmul 可以只算左下角,所以如果是在做自研 CPU 推理方案,在最佳化 batchmatmul 運算元時也可以採用這種方案,可以不用去計算整個正方形的矩陣結果,只計算左下角的部分,這樣冗餘的計算量會小很多,也能進一步最佳化效能。
然後我們在這個基礎上設計了大模型的推理方案,就是把模型拆分成兩個,一個叫 prefill 模型,一個叫 decode 模型。prefill 模型就只處理大模型的首詞過程,而 decode 模型就只處理大模型的出詞過程。
經過一系列實驗,我們把 prefill 模型的 input shape 定為 128,這樣綜合測算下來它的效率是最高的。然後 decode 模型的 input shape 等於 1,這樣它只用來處理 token 的連續出詞過程。
接下來我們再把 prefill 模型和 decode 的模型做一次權重共享,這樣的話它們的 DRAM 體積佔用也能節省下來,並不會因為搭載了兩個模型就出現兩倍記憶體的佔用。
在確定整個 NPU 的推理方案後,我們再總覽一下我們大模型落端的部署鏈路。首先我們要對雲端浮點模型進行輕量化處理,這裡主要分為模型的量化、模型的轉換以及 NPU 側的編譯過程。
過程結束後,我們就可以匯出 NPU 的端側模型,它是經過 INT4 量化的。拿到這個模型之後,我們就可以放到端側部署執行,這裡主要分為 NPU 模型的初始化,以及最後實際推理過程中的 prefill 和 decode 計算。
以上就是我們大模型端側化的整體鏈路。基於之前的體積和記憶體、效能以及功耗的最佳化方案,我們來看看最終的最佳化效果如何。

可以看到 prefill 效能有了質的提升。在我們最新的藍心 3B 以及天璣 9400 的 NPU 上,prefill 的效能達到了 1200 多 token 每秒,這也是得益於 NPU 的高算力,因為它計算大規模矩陣乘的效率非常高。
我們再來代入一下之前的場景,假設我們做文件總結,輸入是 1000 個 token,如果我們有著 1200token 每秒的首詞效能,它預測第一個詞的耗時就在一秒內,這樣使用者體驗也是比較好的。出詞也是達到了 28 token 每秒,功耗成功控制在了一安以內。
前面我們講述了大模型端側化過程當中,針對記憶體、體積、效能、功耗的等等指標的一些最佳化方案,但我們本質還是圍繞著大模型在端側化部署的推理效能最佳化的角度去討論,但實際在業務場景中,模型的推理只是其中一部分。
從業務場景全域性視角來看還有很多問題沒有解決,比如說實際的業務場景存在多種任務,有文字總結、文字潤色以及決策類任務,單一模型是無法平衡所有場景效果的。
難不成我們要在手機裡塞多個大模型嗎?還有不同的場景對效能的要求都不一樣,我們如何兼顧各個場景的最佳體驗?
另外還有非常重要的問題,就是大模型的生產內容是如何保障安全合規,這些問題都需要我們解決。
首先針對多業務場景,我們最終決定採用 1+N 的 LoRA 架構,就是用基座模型搭配若干個 LoRA 小模型來支撐不同的業務場景,這樣我們只需微調 LoRA 的權重就可以滿足不同業務的需求。
而我們單一的 LoRA 模型的體積,最終也是控制在了小於 100M 的水平。這樣只需管控手機中的 LoRA 模型的數量,就能將模型的體積佔用限定在可控範圍內,也能解決引入多個基座模型帶來的體積激增問題。
大家可以看到我們 3B 模型的體積在 2GB,這就意味著在手機裡內建多個基座模型是行不通的。

另一方面我們在工程架構上也做了一些設計,把不同的 LoRA 模型的切換耗時控制在了 100 毫秒左右,並且在整個切換過程中,基座模型的權重是可以藏在記憶體中的,也就是它可以不需要釋放將近 2GB 的記憶體就可以實現 LoRA 的切換,很好保證了實際業務場景的效能。
此外我們針對不同的業務場景還設計了專屬的最佳化方案。首先針對不同上下文長度的場景,我們設計了動態的 kv cache 方案。比如說我們在處理短文字任務時,可能處理的任務都是短句,它整個輸入輸出加起來可能也就不到 500 個 token。但我們在做文字總結場景時,它的文章因為非常長,很可能就會達到 1000 個 token 以上的長度。

那麼針對這兩種場景,我們就配備了不同的上下文模型。比如說針對小於 512 token 的場景,我們配備了 512 cache 的模型。在處理文字總結這種上下文長度達到 2k 的任務時,我們就切換到 2k cache 的模型。
根據 NPU 的推理特性,cache 長度越小,它的推理效能越高,我們實測 512 cache 長度模型的出詞效能在 29 token 每秒,比 2k 長度還是要稍微好一些的。
也就是說我們在分別處理短句任務和長文字任務時會動態選擇最合適的 cache 長度來實現效能的最佳化。未來我們還會支援更多配置,比如說 3k 到 4k,來應對上下文長度更高的一些場景,比如說多模態的一些場景。

另一種情況就是 prompt 重複的場景,其特點就是不同任務的 prompt 模板都是一樣的,可能就是僅尾部的 token 存在區別。而當模板 token 數比較多的時候,如果我們每次推理都重複計算這個 prompt,整個計算就會顯得比較冗餘。
因此我們設計了一種 prompt 快取機制,在推理之後就會將 prompt 模板部分的對應 cache 內容快取下來。在下一次推理過程中,如果我們檢測到它輸入的 prompt 模板的部分 token 是一樣的,就會跳過這部分計算,僅僅計算後面的非重複部分,這種策略在單一場景執行不同計算任務時就能起到效能最佳化的效果。
比如說當 prompt 模板為 300 個 token 時,每次推理的 prefill 耗時能節省 250 毫秒,最佳化也是非常顯性的。
在業務實際上線過程中,我們還根據業務場景的特徵為其配備了不同的效能策略。我們當前的使用者場景分為兩種,分別為流式上屏場景和決策場景。流式上屏場景顧名思義就是閱讀類場景,使用者觸發功能後需要等待一段時間,螢幕去顯示第一個詞,後續再連續出詞並上屏,比如說大家去同 GPT 對話會的過程就是這樣。
閱讀場景的體驗指標只要滿足人眼的閱讀速度就可以了。因此我們在這個場景透過降低效能來進一步實現功耗最佳化,最終取得效能和功耗的完美平衡。我們將出詞控制在了 16 token 每秒的水平,對比峰值效能雖然有所下降,但這個場景的功耗也降低了。

決策場景則是需要所有的詞全部輸出之後才能進行下一步處理,整個出詞過程中不會同使用者互動。最有代表性的場景就是 AI 自動化操作手機的場景,這種場景需要極致效能來滿足快速響應需求,因此我們在該場景將大模型的推理效能推到極致。
這樣根據不同場景的體驗指標來設定對應的效能策略,就能在各個場景都能實現最佳體驗。
最後就是安全合規的問題。我們針對大模型的安全合規設有專門的端側稽核模型,使用者在實際使用端側的過程中,針對使用者的輸入以及大模型的輸出,我們均有稽核模型進行判斷,若是有不合規的內容,我們就會中途中斷返回,從而保證整個過程當中內容的安全性。
我們在其他模態上也有了一些技術成果,比如說在視覺模態實現了端側 AI 消除,單張圖片的全鏈路處理耗時能控制在 6 秒內。在語音模態實現了超擬人音色,也就是所謂的 TTS,首次播放耗時在 300 毫秒以內,出詞效能也滿足了二倍速的標準,在 70 token 每秒左右。另外在視覺多模態的部分,我們實現了圖文問答,單次回答的響應耗時能控制在兩秒內。
我們從大模型的場景展開,再到技術指標以及場景的最佳化,最終這一切都是由我們 vivo AI 研究院的 AI 團隊自研的 VCAP 計算加速平臺作為支撐的。

針對大模型,我們對整個 VCAP 的工程架構進行了升級,在工具鏈以及執行時均針對大模型推理設計了專屬的最佳化模組。比如說我們在推理時可以針對這個業務場景自由選擇推理模式,它既可以是標準的推理模式,也可以是並行解碼的加速模式。
另外我們還有動態 cache、prompt 快取技術以及 LoRA 切換等特性。在硬體層面,我們支援呼叫 CPU 以及高通和聯發科的 NPU 硬體能力。
章蘇遲,vivo AI 研究院高效能計算工程師。於 vivo AI 研究院任職,主要從事 AI 高效能計算方向,負責 NN 網路在移動端的部署與效能最佳化,在 CPU、GPU、DSP 指令集最佳化和 AI 推理框架設計上有豐富經驗,是 vivo 端計算解決方案 VCAP 的主力開發之一。當前正在負責 AI 大模型在移動端的部署與最佳化,解決大模型落端的效能和功耗問題,打造行業領先的端側大模型能力。
首屆 AICon 全球人工智慧開發與應用大會(深圳站)將於 8 月 22-23 日正式舉行!本次大會以 “探索 AI 應用邊界” 為主題,聚焦 Agent、多模態、AI 產品設計等熱門方向,圍繞企業如何透過大模型降低成本、提升經營效率的實際應用案例,邀請來自頭部企業、大廠以及明星創業公司的專家,帶來一線的大模型實踐經驗和前沿洞察。一起探索 AI 應用的更多可能,發掘 AI 驅動業務增長的新路徑!
