iT邦幫忙

2026 iThome 鐵人賽

DAY 30
0
AI Engineering

不是模型太慢,是你沒算過這筆帳:地端 LLM 工程實戰 30 天系列 第 30

Day 30 - 大結局:45 秒到 2 秒的完整帳,以及錢花在哪一階才有感

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260910/20183550V3pRuUO3X7.png
(P.S. 今天2026/9/10 夢限大也迎來了大結局 真是令人失望阿薇姊)

同一台 Mac、同一顆 Qwen3.8-27B、同一組 40 題。起點的中位數 55.2 秒,全部答對。

直接砍到 5 段,量到 11.9 秒,答對數掉到 35。另一輪加進重排、只送 3 段,量到約 12 秒,40 題判分全過。

兩邊都約 12 秒,但不是同一批量的,我不判定誰快。值得追的是另一件事:你砍掉了哪些段落。

昨天收在 LoRA 該掛在哪裡;今天結清三十天前開的兩個場——Day 01 那 45 秒,以及那句「錢花在哪一階才有感」。

https://ithelp.ithome.com.tw/upload/images/20260910/20183550vr3rZvUW2H.png
圖 1:三格都是實測值。第三格是模型階段實測,加上另外量到的重排時間。

這三刀各值多少

四個條件依序是:檢索 20 段+thinking 開+輸出不設上限(起點)→ 關 thinking → 檢索砍到 5 段 → num_predict 封在 160。

https://ithelp.ithome.com.tw/upload/images/20260910/20183550xNLyzF6kjs.png
圖 2:兩本帳差得愈開,那一刀愈是在保尾巴、不是保平均。

先看中位數:砍 prompt 值 30.9 秒,關 thinking 只值 10.3 秒。再看 p95:兩個對調,關 thinking 一口氣值 49.5 秒。

兩本帳排出來的第一名不一樣,不是誰算錯。thinking 的傷害是偏態的——40 題的總輸出中位數 104 個 token,最長一題 937;關掉之後只剩 7,可見那 104 裡幾乎全是 thinking。中位數看不到那條尾巴,p95 看得到。

第三刀是 null result,比「效果很小」更乾脆:輸出上限全程未觸發。 160 次請求的 done_reason 全是 stop封頂那一輪 40 次的最長輸出是 9 個 token,上限 160。那 0.00 秒的差是執行波動。它限制的是長輸出,而這批問數字的題目不會長——本輪沒有驗到

最肥的那一刀也收費,但帳可以不用這樣付

砍 prompt 在中位數帳上最肥,也是三刀裡唯一有準確度代價的:20 段時 40/40,砍到 5 段變 35/40——而那時還有 37/40 的正解留在 context 裡。

掉的五題死法不一樣。兩題正解還在 context 裡、它挑錯格:a09 把 80.3% 答成 88.4%,a20 把 15,671 ms 答成 195 ms。

另外三題是正解真的被砍掉。一題老實回「查無資料」,兩題從別的段落撿了數字;a39 是 0.90%0.91%相對誤差 1.1%,卡在本篇 0.5% 的門檻上。「掉了五題」不等於「開始亂編」。

關 thinking 那一刀零代價,前後答對數一樣。但這批題目正是 Day 16 說的形狀:單跳、答案就是段落裡的一個字串。換成多跳推理,這一刀不能這樣砍。

所以如果這批題目要求維持 40/40,我會停在「關 thinking、保留 20 段」——中位數 42.6 秒

中間我把 k 掃過 15/12/10/8,最好的一格是 39/40。k=15 保住全部正解還是掉一題,那題的正解排第 1 名:縮短 context 本身就會翻答案。

但那不是唯一的選項。病灶很窄:40 題有 27 題的正解本來就在檢索第 1 名,只有三題躲在第 8、10、15 名。為了那三題,另外 37 題也跟著多送了 15 段。

所以我又跑一輪:撈 20 段不變,中間加一個 reranker 重排,只送前 3 段。

送法 prompt 模型階段 正解涵蓋 通過判分
檢索前 20 段 5,598 42.6 s 40/40 40/40
檢索前 5 段 1,489 11.9 s 37/40 35/40
撈 20、重排、送前 3 930 9.5 s 39/40 40/40

重排把 40 題的正解全推進前 5、36 題排第 1。但不是只有「躲太深」一種病:前面那五題裡有兩題正解還在、模型照樣挑錯格,k=15 那題的正解甚至排第 1 還是答錯。先重排再縮短輸入是另一條路,不是唯一解。

重排本身要收費:BAAI/bge-reranker-v2-m3 在 CPU 上把 20 段重排一次,逐題實測中位 2.25 秒(全距 2.08–2.39)。逐題把兩段加起來再取中位數是 11.7 秒——跟直接砍到 5 段量到的 11.9 秒同一個量級。

⚠️ 但這兩個數字不是同一批量的,不可以拿來排名次。拿同一份 prompt 當探針,兩批之間的 prefill 差了兩成四(數字在條件表)——重排那列天生吃虧。換算到同一速率的估計值放在附錄,正文只留量到的。

還有一件事不能含糊。重排送 3 段時,出題時標記的正解只涵蓋 39 題,判分卻過了 40 題。那題是 a16——它問多步推理題多等 108 倍換回幾個百分點,標準答案 46.7 沒有出現在送進去的任何一段裡;但送進去的段落有 Day 16 那張表,100.0% 與 53.3% 並排——答案由 100.0 − 53.3 就推得出來

證據撐得住,只是撐住它的不是我標的那一段。Day 28 分開講的「答對」「引用正確」「證據支持」,在這裡剛好各自不同。

⚠️ k 掃描與這條方案都是在同一組 40 題上調出來的,沒有獨立題集驗證,結論只停在這批題目。

那 45 秒的帳,還是要結

上面那組是我這台 Mac。Day 01 開場那 45 秒是 demo 現場掐的表,逐刀帳來自教材的示範機——一張 4090,不是我這台:

省下 剩餘耗時
關 thinking −27.50 s 17.50 s
修顯存溢位 −12.60 s 4.90 s
檢索與砍 prompt −2.00 s 2.90 s
穩定前綴與封 max_tokens −1.05 s 1.85 s

它是逐項推算,不是逐刀量測。前兩刀做完停在 4.90 秒,就是 Day 01 那句「隔天同一個問題,5 秒」——合計佔整段改善的 93%,零硬體成本。

這張帳把 thinking 排第一,我那張在中位數上排第一的是砍 prompt。連排序都對不上:機器、模型、runtime 全不同,兩份帳只能各自看。

該先做哪一刀,由你的瓶頸決定

這台 Mac 少了「修顯存溢位」那一格——在 4090 那張帳裡,它是第二肥的一刀。

Qwen3.8-27B 的 Q4_K_M 權重是 16.81 GB。一張 12 GB 的卡裝不下,就得走 partial offload,那是 Day 01 講的 GPU 等 CPU 接力;這台 Mac 可用 107.52 GiB,那一刀對它整刀不成立——換來的是另一種痛:prefill 慢。

https://ithelp.ithome.com.tw/upload/images/20260910/20183550ElKqKlB01w.png
圖 3:先看右欄。沒量到的那幾列,我不替它們排名次。

這張表刻意不排名次(理由同前:分屬不同批次)。重排是取代「砍 k」的另一條路,它跑的時候 thinking 已經關了(疊在第一刀之上),但沒跟封頂那刀疊過。

順序本身也會偷走功勞——Day 16 量過,先修溢位再關 thinking,那刀只剩 5.50 秒。

其中一列的判準要寫準:prefix cache 看的是前綴能不能重用,不是人多不多。Day 18 量過,同一個人把時間戳從 prompt 開頭移到結尾,重算的 token 就從 6,494 掉到 31。

倍數不是承諾,是條件句。

一條除法估四種配置

跨配置比較最容易翻車的,是拿不同 backend、不同引擎的 tok/s 直接除。所以統一用一條除法:單流估值 = 帳面頻寬 × 假設 MBU ÷ 每個 step 要讀的權重。

https://ithelp.ithome.com.tw/upload/images/20260910/20183550ovCygCU5uS.png
圖 4:最右欄只有一格有數字,那一格還跟左邊對不上。

它不是上限:上限要能證明不可超越,而 0.6 只是填進去的假設——真實效率高於 0.6 時,實測本來就會超過。

而且它估的是 decode,這批請求真正吃時間的不是它:關掉 thinking 的 120 次裡,decode 只佔模型階段耗時的中位 2.4%(0.3–4.8%);但起點那組開著 thinking 時是中位 19%、最高 70%。decode 佔多少,取決於你有沒有讓它想。

拿這台去對:估值 19.5、實測 10.0。兩個百分比意思不一樣,不可混用——表觀 MBU 31%(實測 tg × 權重 ÷ 帳面頻寬,Day 10 的兌現率口徑)與估值達成率 51%(實測 ÷ 估值)。

而且不只一個答案。Day 10 在這台量到的是 52%——那是 llama-bench、Gemma 4 12B、短 context、-fa off;今天四樣全換。偏離多少算得出來,但歸不了因

所以用法只有一種:這條除法給的是頻寬尺度的初估,實際排名仍要同條件量測。 Day 10 示範過帳面順序被翻盤——546 對 504,換算成權重讀取等效是 284 對 402。它也答不了多人服務:那要看 batching 與延遲目標下的有效吞吐。

錢花在哪一階才有感

https://ithelp.ithome.com.tw/upload/images/20260910/20183550KscO5mWzfM.png
圖 5:換一張卡、換一個電價、換一種請求形狀,這幾個數字全要重算——它是算式,不是結論。

一個月 US$2,631:硬體攤提 $500、電費 $131、人力 0.2 FTE $2,000。電費只佔 5%——只拿電費去跟 API 比,就漏掉另外 95%。

電費那格的假設:GPU 最大功耗 600 W、整機 IT 功耗假設為 GPU 的 1.8 倍、PUE 1.4、整月不停機。少乘 1.8 會少算四成四——而 1.8 本身是假設。

平衡點我原本算錯了方向:同一份瘦身也會改變 API 成本。用起點那組 5,596 token 算,自建打贏 Claude Opus 5 要每天問約 2,900 次;換成重排後那 930 token,門檻跳到約 18,200 次。所以買卡那筆帳,要在優化之後才算

⚠️ 這裡用的是維持 40/40 的形狀。拿前一節那個掉五題的 5 段版算只有 11,500——用掉品質的設定算成本優勢,等於把準確度代價偷偷折現

右欄只是敏感度試算:固定 token 形狀、未計快取折扣。⚠️ 那 930 token 是重排之後才有的形狀——自建這邊 reranker 跑在同一台機器的 CPU 上沒另外計價,換成 API 就得自己補這筆。

這條線只比錢、不比品質:自建跑 27B,被比的是前沿模型;也沒回答「這台能不能在延遲目標內接下這個量」。自建買到的是資源控制權,那不等於 SLA

雲租另有租用時數與維運成本,而不同卡的每小時價格判不了同等能力下誰贏。削峰與 PoC 值得先租。

還有一個口徑陷阱。「5,596 token」是 Qwen 的 tokenizer 數的;Anthropic 講的「多約三成」是 Claude 4.7 相對較早的 Claude tokenizer,不是 Qwen 換 Claude 的換算率。跨家比 $/token 前,先各自數一次。

配置之間買到的是:CUDA 生態與 FP8、容量讓單卡一次裝下(Day 12 那些 NCCL 咒語不用念)、互連。但這四種不是由低到高的階梯——128GB 的 Mac 換 12GB 顯卡,在這顆模型上是容量下降。

但大部分人還沒走到互連那一階,卡的是容量線——而容量線是先把權重、KV、state 與 runtime 預留加起來。這是這 30 天最值錢的東西。

今天的實驗需要什麼

兩個數字就夠:機器的帳面頻寬、模型的權重檔大小。把圖 4 那條除法換成你的卡重估一次,再照瓶頸把圖 3 重排一次。

要自己量的話,形狀很單純:同一組題目、同一批段落,相鄰兩個條件只改一個變數,每題輪轉條件順序,看逐題省時的中位數,再另外比較各條件的 p95。判分規則先寫死再跑。

小結

  • 第一張地圖(量測):把「慢」換成 TTFT/TPOT/E2E,每個數字都標來源與口徑。沒有尺就沒有工程。
  • 第二張地圖(容量線):權重、KV、state、runtime 預留先加起來,再決定動哪個旋鈕。
  • 第三張地圖(吞吐線):前兩刀吃掉幾乎全部的改善,零硬體成本。中位數帳與 p95 帳排出不同的優先順序,先決定你在保哪一個。
  • 第四張地圖(準確度):快而答錯等於零。最肥的那一刀砍掉四分之三的段落,答對數也跟著掉——每一刀都要標它收多少,不是只標它省多少。而真正的解法通常不在「砍多少」,在「砍對哪幾段」。

Day 01 承諾的四樣,最後點一次名:算容量的公式在 Day 09、14 與計算機;加速清單是圖 3;45 秒那份逐項推算帳在上面。

第四樣當初承諾的是兩台機器的第一手數據,這篇交的是一台的完整前後對照:同一台、同一組題、每次只動一個變數。例外是圖 3 的容量那一列——這台撞不到那條線,那一格只有算術。

最後還有一項沒做完:Day 01 點名過 GPU 共享與隔離方案(time-slicing、NVIDIA MPS、HAMi、MIG),這幾樣本篇沒有測試。但它們在解的問題我量了,收在文末附錄。

三十天走完,如果只留一句:買下一張卡之前,先把手上這一張的帳算清楚。

謝謝你陪我走完這 30 天。

下一次有人問你「這台跑不跑得動」,希望你手上有一把尺,而不是一個感覺。


這篇的條件與來源

項目
機器 MacBook Pro M4 Max 128GB,全程 Metal。
runtime Ollama 0.33.3,/api/chatstream:false
模型 qwen3.8:27b-q4_K_M(27.3B、GGUF 磁碟 16.81 GB;另有 0.93 GB 視覺投影器,純文字 decode 不讀)
取樣 temperature 0seed 20260909num_ctx 16384num_predict 依條件為 −1 或 160
語料與檢索 沿用 D25–D28:day01.mdday24.md 切 451 段、BAAI/bge-m3corpus_sha256 開頭 e1cd341b。砍 prompt 砍同一批段落,不換索引
題目 Day 28 的 40 題有解題,四個條件跑滿(160 次請求,86 分鐘)
秒數的口徑 模型階段耗時合計 = 載入 + prefill + decode(Ollama 的三個 duration 欄位)。⚠️ 不含檢索與應用層,不是完整 RAG 的 E2E。重排的秒數是另外量的,跟模型階段相加而成,兩段分開量
圖 4 的實測 decode 取輸出 ≥100 token 的中位數,本批符合的只有 23 次、全部來自開著 thinking 的那一組。門檻的理由是本次觀察:更短的輸出樣本算出來的速率明顯偏高
跨批次的探針 同一份 5 段 prompt(約 1,487 token)在主實驗那批量到 prefill 127.8 tok/s、重排那批只有 97.3 —— 一模一樣的工作負載差兩成四,所以那是機器狀態不是負載差異
統計量 刀帳走逐題配對後取中位數;p95 欄是兩端 p95 相減。不同估計量,不保證相等,不可互相驗算。⚠️ 本篇沒有做同條件重複量測,沒有波動範圍,所以差距小的兩格一律並列不排名
判分 沿用 Day 28:抽得到 gold、或相對誤差 0.5% 內算對(不是差 0.5 個百分點)。門檻刻意從嚴,換一個 a39 就會翻面
prefix cache 每一發在 system 前插唯一標記把它打掉。不打掉會有兩個條件白吃前一發的快取(prefill 從 29.13 秒掉到 0.39 秒),那不是「關 thinking」省的
跑序 條件順序每題輪轉,避免熱衰減全記在同一個條件上。自檢:86 分鐘下來四個條件的 prefill 速度都下降約一成一、降幅接近(全距 1.7 個百分點),未見哪個條件被拖得特別重
k 掃描那一輪 sweep.py,k=15/12/10/8,160 次請求,紀律同主實驗。答對依序 39/38/39/36,沒有一格是 40
重排那一輪 BAAI/bge-reranker-v2-m3、CPU、max_length 512,80 次請求,think:false、輸出不封頂(所以它是疊在第一刀之上,不是獨立的一刀)。正文的 9.5 秒是實測,換算值見附錄
沒有量的 多請求服務的併發與 goodput、streaming 的真實 TTFT。附錄另測了模型之間的資源競爭,那是兩件事
45 秒那張帳 教材示範機(單卡 4090)的推算,不是這台,Day 01 與 Day 09 都標過,與本篇實測不可互相印證
四種配置 頻寬為帳面規格,T3/T4 全季無實機。估值 = 單卡頻寬 × 0.6 ÷ 權重,0.6 是假設不是量測,不是上限。⚠️ T4 的 H100 是既有參照配置,不是硬體頂點。本表只估單卡
TCO 採購價為本例假設:卡 US$13,250 + 主機 US$4,750(2026-08 查價,波動極大)。電價 US$0.12/kWh、整機 IT 功耗假設為 GPU 的 1.8 倍、PUE 1.4、1 FTE US$10,000/月。牌價為 2026-08 官方值。⚠️ 雲租兩個單價來自不同供應商與不同卡,不是同能力比較

附錄:四篇沒發的加碼篇

加碼篇本來排了四篇,後來決定一篇都不發。量到的收在這裡;量不到的,直接說沒量到。

一、一張卡養三張嘴

Day 01 點名的 GPU 共享與隔離方案——time-slicing、NVIDIA MPS(Multi-Process Service,CUDA 的多程序共享;跟下面那個 Apple MPS 只是縮寫相同)、HAMi、MIG——本篇沒有測試。改量它們在解的問題:完全不隔離的共享長什麼樣。

同一顆 27B 生成 200 個 token,旁邊擺一顆 reranker 連續打分,三個條件只差它跑在哪裡。

https://ithelp.ithome.com.tw/upload/images/20260910/20183550TV3GbIJLD3.png
圖 6:兩邊的帳都要記——LLM 被搶走多少,reranker 自己又慢了多少。

挪到 CPU 救得回 decode(掉 76% 收斂到掉 10%),但救不回 prefill——兩種擺法都掉三成上下(32% 與 35%)。而 reranker 自己從每批 2.43 秒變成 6.94 秒,慢了 2.9 倍。

這台是統一記憶體,CPU 與 GPU 吃同一條頻寬——不過這一輪分不出「搶頻寬」與「搶 CPU」各佔多少。能說的只有一句:挪去 CPU 沒有讓 LLM 免疫,只是換一個誰餓。

Day 21 那張顯存預算表回答「塞不塞得下」,這張圖回答「塞下之後誰先餓到」。

二、Mac 上微調 LoRA

Day 29 全程沒開 GPU,只留下一句「這是預算不是實測峰值」。這次真的訓一次——用的是本機的 mlx-lm 0.26.0,而現行發布版已經是 v0.31.3

https://ithelp.ithome.com.tw/upload/images/20260910/20183550lj8OS8mjuf.png
圖 7:預設值會改,開訓前先查你安裝的那一版。

照 Day 29 的參數重跑,峰值 7.92 GiB,比那張預算表最樂觀的一格還低。但工具、模型、量化、記憶體型態四個變因一次全換,只能比量級,不能相除。沒有 held-out 評估,所以不談哪一組比較好。

三、GraphRAG-lite 值不值得

我沒有答案,因為我的尺量不到它

GraphRAG 要解的不只是「串兩段」:官方的查詢模式還包括特定實體的關聯查詢,以及對整份資料集的全局歸納。

而 Day 28 那 40 題是自動生成的數字查找題,出題方式就決定了每題只問一個落在單一段落的數值——30 題只有一段裝著答案,另外 10 題是同一個答案重複出現。關聯查詢、跨段推理、全局歸納,一題都沒有。

所以能給的不是答案,是判準:先看你的題集有沒有這三種題型,再看現有檢索是在哪一種上失敗。gold_chunkgold_cands 只夠做初步盤點——a16 就示範了標記之外還可能有別的證據路徑。

四、三十天索引與計算機

https://ithelp.ithome.com.tw/upload/images/20260910/20183550wGTJO6WZMo.png
圖 8:四張地圖的閱讀順序;準確度的判準要先訂死,不是最後才檢查。

計算機三件套配 66 條錨定測試,對著文章算過的每一格。工具跟文章共用同一套假設,一邊改了另一邊就紅燈。

換算到同一機器狀態的估計值

正文只放量到的秒數。三批分屬不同機器狀態,所以另外換算一版:假設 prefill 都跑在主實驗那批的 129 tok/s。

送法 prompt 固定 prefill 速度下的估計耗時
檢索前 20 段 5,598 43.7 s
檢索前 5 段 1,489 11.8 s
撈 20、重排、送前 3 930 9.8 s(已含重排)

附錄的條件與來源

項目
三張嘴那一輪 qwen3.8:27b-q4_K_MBAAI/bge-reranker-v2-m3(reranker 跑在 torch 的 Apple MPS 後端或 CPU)· 15 題 × 3 條件,輸出固定 200 token、每發打掉 prefix cache、條件順序每題輪轉
倍率的口徑 逐題配對後取中位數。第一發 solo 明顯比後面快(機器還涼),所以不可以拿兩個條件的中位數相除;同一題的三個條件是背靠背跑的,熱狀態最接近
reranker 的基準 每批 20 對,獨占基準跑前跑後各量一次取平均(CPU 2.04/2.82 秒)
熱衰減自檢 solo 的 decode 前半 10.41 → 後半 8.88(掉 14.7%),兩個併發條件幾乎沒動。⚠️ 輪轉與相鄰配對能減少時序干擾,但只憑前後半的衰退無法斷定誤差往哪一邊偏,所以只列數字不下方向判定
沒量到的 GPU 共享與隔離方案本身(time-slicing、NVIDIA MPS、HAMi、MIG)——手上只有這台 Mac。本附錄量的是沒有任何隔離時的共享
微調那一輪 本機 mlx-lm 0.26.0(2025-07-08 發布)· mlx-community/Qwen3-8B-4bit(36 層),120 iters、batch 1、seq 1024,兩組只差 --num-layers。⚠️ 沒有 held-out 評估。⚠️ 2026-09-10 拿發布版本 v0.31.3 的 tag 原始碼逐項對過(不是 main 分支):選層清單已移除(keys 未指定時直接走訪所有可轉換模組,不再 raise ValueError),--num-layers 16scale 20.0 仍成立
GraphRAG 那一節 沒有建圖、沒有跑 LLM 抽實體。只用 Day 28 已有的 gold_chunkgold_cands 欄位數了一次,判準寫在 research/day30/graph.py

上一篇
Day 29 - 32 層只掛到 8 層:微調前,先查你的 LoRA 掛在哪裡
系列文
不是模型太慢,是你沒算過這筆帳:地端 LLM 工程實戰 30 天30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言