瀏覽器跑 LLM 的實際體感與骨感限制
直接在瀏覽器跑 LLM,既兼顧隱私又不用複雜的GPU設定,太完美了吧? 從 WebLLM 到 Transformers.js,前端社群有一群反骨仔吹起一股「邊緣 LLM」的熱潮,可是,當真正將模型落地到使用者的瀏覽器時,第一個面對的考驗就是,WebGPU 真的有比 WASM 快嗎? 這陣子實測的結論比想像中更加戲劇化, 500M 以下的微型模型,WASM 反而快了 12%,但是對於 3B 以上的大模型,WASM 直接變成悲劇,直接讓Chrome撞的頭破血流(Chrome 沒有頭 = Headless Chrome)。 測試環境 項目 規格 機器 MacBook Air M2, 8GB RAM GPU Apple M2, 8 核心 磁碟可用空間 9.7GB 瀏覽器 Chrome 136 (Playwright headless) 框架 WebLLM 0.2.84, @xenova/transformers 2.17.2 一開始遇到我的破MBA 8GB 機型的磁碟剩 9.7GB,這直接觸發了瀏覽器 Cache API 的物理配額限制(約為可用空間的 10%,即 ~970MB),這個限制直接決定了前端能載入的模型體積。 Phi-3.5 Mini @ MBA 原定計畫是測試熱門輕量級模型 Phi-3.5-mini-instruct(3.8B 參數),然而在 8GB MacBook Air 上,模型連載入都不行。 Phi-3.5-mini-instruct-q4f16_1-MLC 需佔用約 2,520 MB VRAM,當權重檔案下載到瀏覽器後,就出線 QuotaExceededError,即使換了一些快取的策略,還是都不行: Cache API(預設):QuotaExceededError: Quota exceeded IndexedDB:ArtifactIndexedDBCache failed to fetch OPFS:SecurityError: unsafe file access 在 8GB 記憶體且磁碟空間不足的裝置上,3.8B 模型完全無法運作,瀏覽器儲存配額(Storage Quota)直接被吃滿。 Phi-3.5 Mini @ MStudio 為了確認是否是儲存配額問題,我改用 M2 Max 運行相同的 WebLLM 代碼與 Phi-3.5-mini-instruct-q4f16_1-MLC 模型: 結果: 指標 M2 Max tok/s 57.4 準確率 90.0%(10 題對 9 題) 總 tokens 956 總時間 16.66s 模型載入 一次成功 輸出 57.4 tok/s 速度在中文字的回覆上極度流暢,簡單的丟了一些問題,數學邏輯題,程式碼產出與生物資訊(Variant calling/WES)相關問答回答的也是有模有樣的。 輕薄的Client跑不動前端 LLM,真正的第一道關卡往往是瀏覽器的 Storage Allocator,而非 GPU 本身,那我的 MBA 到底可以跑什麼模型? 1. TinyLlama-1.1B 改用 @xenova/transformers (v2.17.2) 執行 TinyLlama-1.1B-Chat 時,雖然可成功下載權重,但推理的瞬間會拋出錯誤, RangeError: offset is out of bounds at Uint8Array.set ,餵狗後發現這應該是 舊版 ONNX Runtime Web 處理特定運算子時超越 WASM 記憶體上限的已知issue。 2. SmolLM2-360M 再測試了 SmolLM2-360M-Instruct (q4f16): 速度:38.4 tok/s 聽說底層做了編譯優化,跑起來也是相當的穩定。但 360M 參數推理能力相當有限,回答問題的能力連ChatGPT剛出來時都不如啊... (雖然也知道參數大小差很多,但是已經被LLM寵壞了) WebGPU vs WASM 效能對比 我內心還是覺得應該要公平比較 WebGPU vs WASM在效能上的差異,因此又找了一些模型在MAC Studio 上來比拼,先用 GPT-2(124M)跑了兩輪。 GPT-2(124M)是 2019 年的模型,答題水準大概長這樣... Q: What is 2 + 2? A: The answer is 2 + 2. ← ... Q: How many legs does a cat have? A: The answer is no. ← WTF Q: Write a Python function to add two numbers: A: def add_number(x, y): return x + y + 1 + 1 + 1 + 1... ← 有 def,但多加了一堆 1 Q: What is the capital of France? A: The capital of France is the capital of France. ← 跳針 結果 後端 tok/s 準確率 總時間 WASM 23.2 30% 16.39s WebGPU 20.4 30% 18.68s 在 124M 模型下,WASM 竟然反超 WebGPU 約 12%! 為什麼微型模型下 WASM 會贏? 資料傳送Overhead:Token 需要頻繁在 CPU 與 GPU 記憶體間複製,當計算量不夠大時,搬運時間直接侵蝕效能。 Kernel 啟動成本:每次啟動 GPU Kernel 都有固定開銷,無法被小規模平行運算攤平。 WASM 的進化:成熟的指令集與 JIT 優化,已足以讓 CPU 高效處理 124M 規模的矩陣運算。 3.8B 模型對比 上面 GPT-2 的結論是「124M 小模型 WASM 贏 12%」,好像就直接打臉我上一篇的農場標題XD TensorFlow.js 快看不到 LiteRT.js 的車尾燈了 , 那如果換成更大的模型呢?我在 M2 Max上用同一個 Phi-3.5-mini-instruct-q4f16_1 模型分別跑了 WebGPU和 WASM,來看看結果如何。 後端 tok/s 準確率 總 tokens 總時間 WebGPU 59.7 70%(10 題對 7 題) 490 8.20s WASM 0.5 60%(10 題對 6 題) 413 827s(13.8 分鐘) 結果看去裡,WASM 慢了 119 倍,總共 10 題要跑將近 14 分鐘,而且單題延遲 72-100 秒,WebGPU 只要 0.8 秒左右。 為什麼差這麼多?合理的推測是因為 WASM 是 CPU 跑,CPU 的記憶體頻寬和算力是固定的 (還是MAC的CPU問題?),而模型從 124M 漲到 3.8B,每單位 token 的計算量跟著漲,但 CPU 的速度不會變。WebGPU 則是把運算丟給 GPU 的 parallel cores,理論上模型越大、GPU 的相對優勢越明顯。 反而像GPT-2 那種 124M 的規模,GPU 的 kernel 啟動和資料傳輸開銷反而吃掉平行化的好處,超過某個臨界點(大概 1B 左右)之後,WebGPU 的優勢就出現了。 又手癢補跑了一顆更大的模型 Qwen2.5-7B-Instruct(7B,q4f16)在 WebGPU 上: 指標 數值 tok/s 35.5 準確率 80%(10 題對 8 題) 總 tokens 643 總時間 18.13s 7B 的模型在瀏覽器裡能跑到 35.5 tok/s,還能答對 8 題,不過這顆模型的變異較大,跑起來很明顯的卡頓與瀏覽器快往生的感覺,又回頭處理scaling 的部分,Phi-3.5 Mini 在 WebGPU 上把 max_tokens 從 50 拉到 400,準確率從 70% 升到 100%,tok/s 穩定在 59.7-65.2 之間,給模型更多生成空間,答案品質會明顯變好,而且速度幾乎不受影響。 小結 小模型不用硬上 WebGPU:若任務僅需 1B 模型時,除了關心使用者的顯示卡,務必優先檢查 Storage Quota。使用者硬碟空間不足導致的快取失敗,往往才是用戶體驗崩潰的主因。
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to