同一個 gemma4:e4b,搬到 AMD Renoir iGPU + Vulkan 上跑,速度快 8 倍,答案卻全錯——問技術問題,回你泰文學習理論。這不是模型笨,是硬體/後端把數字算歪了。這張診斷樹把整段排查攤開。
flowchart TD S["症狀: gemma4:e4b 在 iGPU 超過 30 層吐亂碼
低層數正常, 速度快但答案全錯"]:::proc S --> A{"先懷疑: RAM 不足?"}:::decision A -->|停 OMS 釋放記憶體| A2[["iGPU 靠 UMA 2GB + GTT 動態借 RAM
RAM 不足 GPU 借不到頁面 → 崩潰重試"]]:::infra A2 --> B{"二分法: 幾層開始壞?"}:::decision B -->|num_gpu 1~5 正確| B1["✅ 少數層 正確"]:::proc B -->|num_gpu 20+ 亂碼| B2["❌ 誤差隨層數累積"]:::proc B1 --> C{"調環境變數能修嗎?"}:::decision B2 --> C C -->|GGML_VK_DISABLE_F16=1| C1["無效"]:::proc C -->|OLLAMA_KV_CACHE_TYPE=f32| C2["輸出變旁遮普語"]:::proc C1 --> R(["根因: RADV/ACO 編譯器層
重排 FP16 運算順序 → 每層小誤差
層層放大, 第 30+ 層蓋過真訊號"]):::result C2 --> R R --> F(["解法: num_gpu=0 純 CPU 慢但全對
或換 Mac Metal 同速且精度正常"]):::result classDef data fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#78350f classDef proc fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#17335e classDef decision fill:#ede9fe,stroke:#7c3aed,stroke-width:2px,color:#4c1d95 classDef result fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d classDef infra fill:#e5e9f0,stroke:#475569,stroke-width:2px,color:#1e293b
現象:模型反覆崩潰重試,載入耗時 6 分鐘
測試:停掉 OMS 服務,把系統 RAM 讓出來
結論:iGPU 記憶體 = UMA(2GB 固定)+ GTT(動態借系統 RAM)
系統可用 RAM 不足時,GPU 借不到足夠頁面 → 崩潰num_gpu = 1~5 ✅ 正確 num_gpu = 10 ⚠️ 不穩定 num_gpu = 20+ ❌ 亂碼 發現:誤差隨「丟給 GPU 的層數」累積,越多層越糟
GGML_VK_DISABLE_F16=1 → 無效 OLLAMA_KV_CACHE_TYPE=f32 → 輸出變旁遮普語(還是錯) 結論:bug 在 RADV/ACO compiler 那一層,應用層無法控制
層內:RADV/ACO 為了優化,重排 FP16 運算順序
浮點數不符結合律 → 順序一改,結果就變
層間:每層輸出是下層輸入,小誤差被逐層放大
第 30+ 層後,累積誤差已蓋過真正的訊號「快 8 倍但答案全錯,還不如 1 tok/s 的純 CPU」
建議:num_gpu=0(純 CPU,1 tok/s 但完全正確)
或換 Mac Metal(同速,但精度正常)| 類別 | 文章中出現的實際名詞 |
|---|---|
| 硬體 | AMD Renoir APU、Vega 架構 iGPU |
| 模型 | gemma4:e4b(共 43 層) |
| 後端 / 執行層 | Vulkan(RADV / ACO compiler)、llama.cpp、Ollama |
| 精度 / 記憶體術語 | FP16、FMA、denormal、UMA、GTT |
📺 對應單集:地端模型的限制:記憶體、GPU 怎麼看 | 📚 回課綱總表 →