iT邦幫忙

0

本地跑模型做評測,你們是怎麼給 context 長度設上限的?我們沒設,7.1 GB 的模型吃掉了 51 GB

  • 分享至 

  • xImage

先說清楚身分,免得被當成來打廣告的:我是 LibreDB Studio 的維護者之一,那是一個 MIT 授權的開源資料庫 IDE。下面的數字都是我們自己連續跑了 11 天測出來的,不是抄文件。

我們踩到的

為了搞清楚小參數的開源模型到底能不能驅動 Agent,我們把 39 個開源權重模型全部走 Ollama 跑在本地,6 類任務,總共 8,199 次執行。

中間有一批資料被污染了,回頭複查才找到原因:

不限制 context 長度的時候,一個 7.1 GB 的模型會照它完整的 262,144 token 視窗去要記憶體,在一台 64 GB 的機器上實際佔到 51 GB。

最難受的不是佔得多,是日誌裡看不出來。你只會看到一次沒跑完的執行,和「模型逾時」長得一模一樣,沒有 OOM,也沒有明確的錯誤訊息。我們早期有一批評測結果就是這樣廢掉的。

把 num_ctx 固定到 32,768 之後,同一個模型掉到 5.1 GB,而且有一個 3B 模型的某類任務直接從 0/5 變成 5/5。也就是說,我們本來以為「這個模型不行」,其實是記憶體被 context 吃光了。

想請教的

  1. 你們在本地跑模型的時候,怎麼給 context 長度定上限?按記憶體比例算,還是固定值,還是按任務類型分檔?有沒有一條能用的經驗公式?

  2. 有沒有辦法在執行前就判斷「這個設定會不會爆記憶體」,而不是跑掛了再回頭查?我們現在是跑之前先粗算一遍,但算得很粗。

  3. 這種「看起來像逾時、其實是記憶體」的狀況,你們一般怎麼在日誌裡分辨?我們現在是額外記一筆記憶體取樣,但總覺得有更省事的作法。

完整資料、評分腳本和論文都公開了:https://arxiv.org/abs/2609.21341

如果你們也在本地跑模型做評測,這一條值得回去翻一下自己的資料,我們就是這樣發現的。

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
helenanova
iT邦新手 5 級 ‧ 2026-09-25 19:10:21

我們的原則是把 num_ctx 當成評測的固定參數,不是資源問題。它會改變結果——你們那個 3B 從 0/5 變 5/5 就是證明——所以它應該跟 temperature 一樣寫進每次執行的紀錄,同一批評測用同一個值,不然不同模型其實是在不同條件下比。

上限怎麼定:按任務實際需要的長度定,不按記憶體上限定。先抽樣量一下各類任務實際 prompt 的長度分佈,取 p95 再加輸出預留,通常遠小於「記憶體裝得下多少給多少」,也比它穩。對多數 agent 任務,32k 已經很奢華。

執行前判斷會不會爆:KV cache 的大小是可以估的,大約是 2 × n_layers × n_kv_heads × head_dim × num_ctx × 每元素位元數,權重加上這個數字再加兩成餘量,跟可用記憶體比就知道。更省事的做法是把它變成 pre-flight:整批開跑前,先用一條長度接近 num_ctx 的 prompt 做一次 30 秒的冒煙測試,過了才正式跑。

「看起來像逾時、其實是記憶體」:與其事後從日誌分辨,不如讓它沒辦法安靜地死。把 runner 放進有記憶體上限的 cgroup(或 docker --memory),記憶體真的不夠會變成明確的 OOM kill(exit 137),跟逾時是兩種完全不同的訊號。取樣當然也行,但「把模糊的失敗變成明確的失敗」通常比「把日誌記得更細」划算。

libredb iT邦新手 5 級 ‧ 2026-09-26 01:40:36 檢舉

謝謝,這四點都比我們原本想的乾淨。

第一點我們接受,而且它比我們原本的說法更準。我們一直把 num_ctx 當成環境問題,所以它沒進紀錄,只在出事以後回頭查。照你的說法它跟 temperature 同級,那我們那批 8,199 次執行裡,前面沒固定 num_ctx 的部分嚴格講不是同一組條件下的比較,只能當線索。這一條我們會寫回論文的限制段,不是補在附註裡。

p95 加輸出預留這個定法我們沒試過,之前是反過來做的:看機器有多少記憶體,再決定給多少。你說的 32k 對多數 agent 任務已經很奢華,跟我們的實測對得上,我們固定到 32,768 之後沒有任何一類任務因為長度不夠而失敗。

KV cache 那條公式我們會拿去對一次。手上剛好有數字可以驗:同一個 7.1 GB 的模型,不設上限時吃到 51 GB,設 32,768 之後掉到 5.1 GB。如果公式估得準,這兩個數字應該都能算出來。算不準的話那才是真的有東西沒看懂。

最有用的是最後一點。我們之前的方向是「把日誌記得更細」,額外記一筆記憶體取樣,再回頭比對。你講的是反過來,讓它沒辦法安靜地死。cgroup 或 docker --memory 加上去之後,記憶體不足會變成 exit 137,跟逾時是兩個完全不同的訊號,根本不需要分辨。這件事我們自己想了十天都沒想到,因為一直在想怎麼「看出來」,沒想過怎麼「讓它必須說出來」。

冒煙測試那個也會加。整批跑之前先用一條接近上限長度的 prompt 跑 30 秒,比跑到一半才發現省太多了。

再次感謝,這幾條都會進我們的執行流程。

我要發表回答

立即登入回答