首頁 / 本地大模型

本地大模型顯存怎麼估算?依顯示卡顯存挑模型的方法

作者 JC · 更新於 · 最後查證

重點速覽

本地大模型顯存需求約等於「權重大小+KV cache+執行時額外開銷」。權重大小用「參數量 × 每個權重平均位元數 ÷ 8」估算,KV cache 用層數、KV 頭數、每頭維度、上下文長度與每個元素的位元組數相乘,算出來再留約 1 GiB 餘裕,就能事先判斷放不放得下。

想知道手上的顯示卡跑不跑得動某個模型,關鍵在於估好本地大模型顯存:模型權重多大、對話越長 KV cache 多大、再加上執行時的額外開銷。這篇會把三項拆開,各給你一條可以自己代入數字的算式,最後整理成對照表和判斷步驟。讀完之後,你不需要先下載幾十 GB 的檔案才知道放不放得下。

為什麼顯存是第一道限制?

顯存(VRAM)是顯示卡上的專用記憶體,GPU 計算時要用的資料,最理想的情況是整份放在這裡。大型語言模型(LLM,大型語言模型,見術語表)稠密模型(每一層的所有權重都會參與運算的一般模型,和之後會談到的 MoE 相對)生成每一個字,都得用到全部的權重,所以權重放不進顯存,就只能放在相對慢的系統記憶體(llama.cpp 的多 GPU 說明就是這樣描述的),甚至根本載入失敗。

Hugging Face 的官方教學給過一條很直接的經驗法則:載入一個有 X 十億參數的模型,用 float32 大約需要 4 × X GB,用 bfloat16 或 float16 大約需要 2 × X GB。同一份教學也提到,輸入文字比較短(少於 1024 個 token)時,推論的記憶體需求主要由載入權重決定。token 是模型處理文字的最小單位,詳見術語表。

但文字一長,另一塊就會長大。所以完整的估算要拆成三項:

顯存需求 ≈ 權重大小 + KV cache + 執行時額外開銷
  • 權重大小:模型本身的檔案內容,由參數量和量化方式決定。
  • KV cache:推論時為每個已處理的 token 暫存的注意力 key/value,長度越長越大。
  • 額外開銷:計算過程的暫存空間、多模態元件等,不同工具各不相同,只能留餘裕。

下面依序處理。為了避免單位混亂,本文一律用 GiB(1 GiB = 2^30 位元組,約 1.0737 × 10^9 位元組,這是算術換算)。工具或系統顯示的是 GB 還是 GiB 可能不同,兩者差約 7%,這也是估算要留餘裕的原因之一。

第一項:權重大小怎麼估?

量化(quantization)是把模型權重改用更少的位元儲存,讓模型變小。它的完整原理和各種格式的差別放在量化是什麼,這裡只需要一個結論:每個量化格式都有一個「每個權重平均用幾個位元」的數字,叫做 bits per weight(bpw)。有了它,權重大小就是一道簡單的乘除:

權重大小(位元組)= 參數量 × 平均每個權重的位元數 ÷ 8
權重大小(GiB)  = 上式 ÷ 2^30
  • 參數量:模型有幾個權重,例如「8B」就是 8 × 10^9 個。
  • 平均位元數:量化格式決定。除以 8 是因為 1 位元組有 8 個位元。

各量化格式的平均位元數

llama.cpp 的量化工具說明,以 Llama-3.1-8B 為例,列出了每種量化的 bits/weight 和檔案大小。下表摘出常用的幾種(數字照原表):

量化格式bits/weight(Llama-3.1-8B)檔案大小(GiB,原表)
Q2_K3.15932.95
Q3_K_M3.99603.74
Q4_K_M4.89444.58
Q5_K_M5.70365.33
Q6_K6.56336.14
Q8_08.50087.95
F1616.000514.96

這張表有兩件事要注意。第一,平均位元數都比名字裡的數字高一點,例如 Q4_K_M 的平均是 4.8944 而不是 4。原因在於量化工具預設會用「k-quant 混合」,不同的張量(tensor,模型內的一塊權重矩陣)用不同的量化類型;官方的選項說明裡有 --pure,作用就是關掉這種混合、讓所有張量用同一種類型。第二,這張表是針對 Llama-3.1-8B 量出來的,換一個模型,各層組合不同,平均位元數會有些差異,所以這裡拿它當估算用的近似值。

用原表驗算公式

量化說明的另一張表把 Llama 3.1 的「8B」模型的原始大小(F32)寫成 32.1 GB。F32 每個權重 4 位元組,所以參數量約為:

示範計算:
參數量 ≈ 32.1 × 10^9 ÷ 4 ≈ 8.025 × 10^9
Q4_K_M 權重 ≈ 8.025 × 10^9 × 4.8944 ÷ 8 ≈ 4.91 × 10^9 位元組
            ≈ 4.91 × 10^9 ÷ 1.0737 × 10^9 ≈ 4.57 GiB

原表寫的是 4.58 GiB,和算出來的 4.57 差在四捨五入內。也就是說,公式沒有問題,只要把參數量和平均位元數代進去就行。

第二項:KV cache 怎麼估?

它存了什麼

語言模型是一個字一個字往後生成的,每預測下一個 token,都需要前面所有 token 的資訊。Hugging Face 的說明這樣描述:KV cache 把前面已處理 token 在注意力層算出來的 key 和 value 存起來,之後直接取用,不必重算。它是每一層各存一份,並且每處理一個新 token,就把新的 key/value 接在後面,所以序列越長,快取就越大;文件也提到這個快取只用在推論,不用在訓練。

這就是為什麼同一個模型,對話越長,顯存用得越多。上下文長度(context window,模型一次能參考的 token 數,見術語表)拉長一倍,KV cache 也跟著大約增加一倍。llama.cpp 的多 GPU 說明在談 OOM(顯存不足)時,也把「KV cache 大致和 n_ctx 成正比」當成調整的依據。

公式

KV cache(位元組)
  = n_layer × n_ctx × n_head_kv × (key_length + value_length) × bytes_per_element
  • n_layer:層數(區塊數)。每一層各有一份快取。
  • n_ctx:你實際設定的上下文長度(token 數),不是模型最大支援的長度。
  • n_head_kv:key/value 的頭數。
  • key_length、value_length:每個 key 頭、value 頭的維度。多數情況下兩者相同,統稱「每頭維度」,所以括號內也可寫成 2 × 每頭維度(2 代表 key 和 value 各一份)。
  • bytes_per_element:每個數字佔幾位元組。llama.cpp 伺服器說明列出 KV cache 的資料類型預設是 f16,也就是 16 位元,等於 2 位元組。

這個算式和 Transformers 教學裡的算式是同一回事:該教學寫「要存的浮點數個數 = 2 × 序列長度 × 注意力頭數 × 每頭維度 × 層數」,並用它的示範模型在 16000 個 token 時算出約 80 億個數字,以 float16 儲存約 15 GB,大約是模型權重的一半。

為什麼是「KV 頭數」而不是「注意力頭數」

那份教學後面接著說明了兩種減少 KV cache 的架構:多查詢注意力(MQA)讓所有注意力頭共用一組 key/value,分組查詢注意力(GQA,Grouped-Query Attention)則是用比注意力頭數少的 n 組 key/value(文件舉的例子是 2、4 或 8 組),保留了 MQA 大部分的記憶體與速度好處。文件也寫道:若模型要處理很長的輸入,例如聊天,強烈建議使用 GQA 或 MQA。

所以公式裡要用「KV 頭數」。同樣是 32 個注意力頭的模型,有沒有用 GQA,KV cache 可以差好幾倍(見下面的示範)。

公式裡的數字去哪查?GGUF metadata

GGUF 是 ggml 生態系使用的模型檔案格式,一個檔案就包含載入模型所需的所有資訊。它用「鍵值對」的 metadata 儲存超參數。GGUF 規格定義了下列欄位([llm] 代表架構名稱,例如 llama):

公式中的量GGUF metadata 欄位規格上的說明
n_layer[llm].block_count注意力加前饋層的區塊數,不含輸入與嵌入層
n_head_kv[llm].attention.head_count_kv不存在,或等於 head_count 時,表示模型沒有使用 GQA(此時 KV 頭數就是 head_count)
key_length[llm].attention.key_length選填;未指定時等於 embedding_length ÷ head_count
value_length[llm].attention.value_length選填;未指定時等於 embedding_length ÷ head_count
模型最大上下文[llm].context_length模型訓練時的上下文長度;多數架構以此為輸入的硬上限

補充一個容易卡住的地方:規格對 head_count_kv 的英文描述是 “the number of heads per group used in Grouped-Query-Attention”,字面有點拗口,但它緊接著的判斷規則是「不存在或等於 head_count 就代表沒有用 GQA」,這只有把它讀成「KV 頭數」才說得通,所以公式裡的 n_head_kv 就是它。

也就是說,你不需要憑印象猜層數和頭數,這些數字是模型自己帶著的。至於用哪個工具把 metadata 印出來,各家介面不同,這裡不寫步驟,請查你所用工具的說明。另外,不同架構可能多出額外的欄位,實際以你手上那個模型檔案為準。

示範計算:假設的模型

以下是完全假設的模型,數字是為了好算而編的,不是任何真實模型的規格:

假設模型 A:
  n_layer = 32
  n_head_kv = 8
  key_length = value_length = 128
  bytes_per_element = 2(f16)

n_ctx = 8192:
  32 × 8192 × 8 × (128 + 128) × 2
  = 1,073,741,824 位元組 = 1 GiB

n_ctx = 32768(長度變 4 倍):
  32 × 32768 × 8 × 256 × 2 = 4 GiB

若同一模型沒用 GQA,n_head_kv = 32(n_ctx = 8192):
  32 × 8192 × 32 × 256 × 2 = 4 GiB

另一個假設模型 B(n_layer = 64,其餘同 A)、n_ctx = 8192:
  64 × 8192 × 8 × 256 × 2 = 2 GiB

從這個算例可以看到:上下文長度 ×4,KV cache 就 ×4;KV 頭數多 4 倍,KV cache 也多 4 倍;層數多一倍,KV cache 也多一倍。

估算會偏高的情況

有些模型不是每一層都存完整長度的快取。Transformers 的 KV cache 說明提到,使用滑動視窗注意力(sliding window attention)或分塊注意力(chunked attention)的模型,那些層的快取長到視窗或區塊大小就不再增加。遇到這類模型,用上面公式算出來的值會偏保守,偏高總比偏低安全。

KV cache 的資料類型可以改

llama.cpp 伺服器說明列出 --cache-type-k 與 --cache-type-v 兩個選項,可選的類型包括 f32、f16、bf16、q8_0、q4_0 等,預設為 f16。也就是說,KV cache 的位元數是獨立於權重量化設定的。把它換成位元數較少的類型,公式裡的 bytes_per_element 就變小,但官方並沒有在那份說明裡說明對輸出品質的影響,所以要不要這樣做,請自己驗證。選項名稱與可用值會隨版本變動,以官方說明為準。

第三項:額外開銷要留多少?

額外開銷是三項裡最難精準估算的,因為它取決於你用的工具和設定。官方說明能確認的是這幾點:

  • 留餘裕是工具自己的做法。 llama.cpp 的 --fit 預設是開啟的,會自動調整你沒指定的參數讓模型放進裝置記憶體,而且 --fit-target(每個裝置保留的餘裕)預設是 1024 MiB。本文的示範採用一樣的數量級:至少保留 1 GiB。
  • 同時處理的對話數也算。 llama.cpp 的多 GPU 說明提到,llama-server 每個同時進行的序列會各配置一份 KV cache,所以要降低顯存壓力,可以降低 --parallel。
  • 多模態元件也會佔位置。 llama.cpp 的多模態說明寫到,多模態投影器(mmproj)預設會被放到 GPU 上;如果你載入的是能看圖的模型,這一份要另外算。
  • 注意力計算本身也有暫存空間。 Transformers 的教學說明,標準自注意力在運算時的峰值記憶體會隨輸入長度平方成長,而 Flash Attention 可以讓記憶體成本只隨長度線性增加。實際用了哪種實作,取決於工具與設定。

另一個容易混淆的地方是:llama.cpp 的 -c(上下文長度)預設是 0,代表「從模型讀取」,也就是可能直接取模型訓練時的長度;而在 --fit 開啟時,伺服器說明提到載入的實例會取「載入當下放得下的最大上下文」。換句話說,如果你沒有自己指定,看到顯存被吃得很滿,不代表模型權重本身那麼大,可能只是工具把剩下的空間拿去放更長的上下文。你想要精準控制時,就自己設定上下文長度。這些預設值屬於會變的細節,以官方說明為準。

比較表一:模型大小 × 量化 → 權重所需 GiB

下表是純算術的示範計算:參數量取整數(單位 10^9),平均位元數取上面的 Llama-3.1-8B 表,套用「參數量 × bpw ÷ 8 ÷ 2^30」。它不代表任何特定模型的實際檔案大小,真實檔案會因架構和量化組合而略有不同。

參數量Q3_K_MQ4_K_MQ5_K_MQ6_KQ8_0F16
4B1.92.32.73.14.07.5
8B3.74.65.36.17.914.9
14B6.58.09.310.713.926.1
32B14.918.221.224.531.759.6
70B32.639.946.553.569.3130.4

單位:GiB,只含權重。要放進顯存,這個數字之外還要再加 KV cache 和餘裕。

比較表二:我的顯存大約能放多大的模型?

下一張表把方向反過來:已知顯存,問「權重預算」有多少,再反推最大參數量。這張表有兩個假設前提,請務必看清楚:

  1. KV cache 取上面「假設模型 A、上下文 8192」的 1 GiB。
  2. 額外開銷取 1 GiB 的餘裕。

所以權重預算 = 顯存 − 1 − 1 = 顯存 − 2(GiB)。最大參數量 = 權重預算 × 2^30 × 8 ÷ bpw。

顯存容量(GiB)權重預算(GiB)Q3_K_MQ4_K_MQ6_KQ8_0
648.6B7.0B5.2B4.0B
8612.9B10.5B7.9B6.1B
121021.5B17.6B13.1B10.1B
161430.1B24.6B18.3B14.1B
242247.3B38.6B28.8B22.2B

這是示範計算,不是保證。你的模型如果層數更多、沒用 GQA,或你要的上下文更長,KV cache 就會超過 1 GiB,表中的數字要往下調;反過來,上下文很短時,才有往上的空間。另外它只適用於「全部權重都放進顯存」的稠密模型;混合專家模型要看下一節。

判斷放不放得下的步驟

  1. 查你能用的顯存。 看顯示卡的顯存總容量,再扣掉其他程式正在佔用的部分。把單位統一成 GiB。
  2. 決定要看的模型與量化。 取得參數量,以及你想用的量化格式。直接看 GGUF 檔案大小最準,因為那就是權重;沒有的話,用「參數量 × bpw ÷ 8」估算。
  3. 決定你實際要用的上下文長度。 不要用模型的最大值,用你真的需要的。一般聊天和讀長文件需求差很多。
  4. 讀出 KV 公式要用的數字。 從 GGUF metadata 找 block_count、attention.head_count_kv(沒有就用 head_count)、key_length 與 value_length(沒有就用 embedding_length ÷ head_count)。
  5. 算 KV cache。 代入公式:n_layer × n_ctx × n_head_kv × (key_length + value_length) × bytes_per_element,f16 時 bytes_per_element 為 2。
  6. 加總並留餘裕。 權重 + KV cache + 至少 1 GiB 餘裕。如果有多模態元件或同時多個對話,也要分別加上去。
  7. 比較。 總和小於你的可用顯存,就放得下;小一點不多就是勉強,建議降低上下文或換更小的量化。

完整示範:同一個假設模型,在兩種顯存下的判斷

假設有一個 8B 的稠密模型(8 × 10^9 個參數),KV 部分用上面的假設模型 A(8192 上下文時為 1 GiB),餘裕 1 GiB:

Q4_K_M 權重 = 8 × 10^9 × 4.8944 ÷ 8 ÷ 2^30 ≈ 4.56 GiB
總需求 ≈ 4.56 + 1 + 1 = 6.56 GiB

  顯存 8 GiB:6.56 < 8   → 放得下,剩約 1.4 GiB
  顯存 6 GiB:6.56 > 6   → 放不下

6 GiB 時的調整方案:
  (a) 上下文減半到 4096:KV ≈ 0.5 GiB → 4.56 + 0.5 + 1 = 6.06 GiB,仍略大於 6
  (b) 改 Q3_K_M:權重 = 8 × 10^9 × 3.9960 ÷ 8 ÷ 2^30 ≈ 3.72 GiB
      8192 上下文:3.72 + 1 + 1 = 5.72 GiB → 小於 6,但只剩約 0.28 GiB,很緊
      4096 上下文:3.72 + 0.5 + 1 = 5.22 GiB → 較有餘裕

這個算例也說明為什麼要同時看三項:光看「Q4_K_M 的檔案只有 4.6 GiB,6 GiB 的顯存放得下」會誤判。

放不下時有哪些選項?

大致照「代價由小到大」排列:

  1. 縮短上下文。 對 KV cache 影響最直接,因為它和長度大致成正比。llama.cpp 的多 GPU 說明在談顯存不足(OOM)時,也是依「破壞性由小到大」排列,第一項就是降低 --ctx-size。(它談的是多 GPU 的情境,這裡借用它的排序來說明各選項的代價。)代價是模型一次能參考的內容變少。
  2. 減少同時處理的對話數。 如果你用伺服器模式開了多個並行序列,每個序列都有各自的 KV cache,降低並行數可以直接省下顯存。
  3. 換更小的量化。 例如從 Q6_K 降到 Q4_K_M,權重大小按表一直接縮小,代價是精度損失可能變大。量化工具的官方說明明白寫著,量化「可能帶來一些精度損失」。各格式的差別與取捨請看量化是什麼。
  4. 把部分層放到系統記憶體。 llama.cpp 的專案簡介列了「CPU+GPU 混合推論」,讓大於顯存的模型可以部分加速;伺服器說明裡的 --n-gpu-layers 決定最多幾層放進顯存。但官方也提醒,被放在 CPU 上執行的層,推論會慢很多。顯存、記憶體和硬碟各自的分工,請看顯存、記憶體、硬碟各扮演什麼角色。
  5. 改用混合專家(MoE)模型。 但要注意它不是「便宜的大模型」,詳見下一小節。
  6. 換成參數量更小的模型。 最直接,但能力也跟著下降。

這些做法對速度的影響,只能定性說:多數情況下,越多東西被擠出顯存,生成速度越慢。怎麼正確地量速度、怎麼讀 tokens/s,請看 Token/s 怎麼看與正確的速度測試方法。

MoE 模型的顯存怎麼估

混合專家(Mixture of Experts,MoE)模型把前饋層拆成多個「專家」,每個 token 只會啟用其中幾個。細節在MoE 混合專家模型,這裡只談對顯存的影響。Transformers 的 Mixtral 說明給了很清楚的例子:Mixtral 有 8 個專家,總參數量是 450 億,但單次前向運算所需的計算量和一個 140 億參數的模型相當,因為每個 token 只分配給兩個專家;不過文件同時指出,所有專家都需要載入記憶體。

所以估權重時要用總參數量,不是啟用的參數量:速度比較像小模型,但權重大小要照整個模型算。llama.cpp 的伺服器說明另有 --cpu-moe 與 --n-cpu-moe 選項,作用是把 MoE 的專家權重留在 CPU 端;這是把「放不下的部分」交給系統記憶體的一種做法,同樣屬於會變的參數名稱,以官方說明為準。

工具範例

如果你想看到實際的工具如何在顯存有限的電腦上載入大模型,可以參考Strata vs PolyStrata 差別比較,該篇依顯示卡等級介紹了兩個本地大模型工具的選擇。

常見誤解

誤解一:把系統記憶體當顯存。 「我的記憶體有 32GB,所以可以跑 30GB 的模型」是常見的誤判。系統記憶體當然能放得下檔案,但 GPU 並不會直接用它計算;llama.cpp 官方的說法是,混合推論只能「部分加速」大於顯存的模型,而留在 CPU 的層會慢很多。有些工具的需求規格會用「RAM 加顯存合計」來表示(本站的 Strata vs PolyStrata 比較就是這樣列的),那代表的是「載得進去」,不等於「跑得快」。

誤解二:只看檔案大小。 檔案大小只回答了權重那一項。同一個模型,上下文設 4096 和設 32768,KV cache 可以差好幾 GiB(見前面的示範)。

誤解三:忽略上下文長度。 模型說明頁寫的「支援幾 K 上下文」,在 GGUF 規格裡對應的是 context_length,意思是模型訓練時的上下文長度,是輸入的上限,不是你必須使用的長度。你設多長,KV cache 就依多長配置。

誤解四:顯存被吃滿,就代表模型很大。 前面說過,有些工具在你沒指定時,會把剩餘空間拿去放更長的上下文。要判斷模型本身的需求,看權重和你指定的 KV cache,而不是看工具或系統顯示的顯存使用量。

誤解五:選了 Q4 的模型,KV cache 也跟著變 4 bit。 權重量化和 KV cache 的類型是兩個獨立的設定,KV cache 預設是 f16。

誤解六:算得進去就一定順暢。 估算只回答「放不放得下」。放得下之後的速度,還取決於其他因素(例如記憶體頻寬與你用的工具);餘裕太小時,只要多開一個程式或把上下文拉長一點,就可能出現顯存不足。

延伸閱讀

常見問題

本地跑大模型至少要多少顯存?

沒有固定答案,要看模型大小、量化和上下文長度。估算方式是「權重+KV cache+額外開銷」:權重 ≈ 參數量 × 每個權重平均位元數 ÷ 8,例如 8B 模型用 Q4_K_M 約 4.6 GiB(示範計算),再加上 KV cache 和約 1 GiB 的餘裕,就是你至少要準備的顯存。

顯存不夠的話,可以用系統記憶體補嗎?

可以,但會變慢。llama.cpp 官方說明有 CPU+GPU 混合推論,讓大於顯存的模型也能執行,但留在 CPU 上執行的層,官方也說明推論會慢很多。系統記憶體是補救手段,不等於顯存。

上下文長度會多吃多少顯存?

KV cache 的大小大致和上下文長度成正比(llama.cpp 官方說明的說法是 roughly proportional)。以文中假設的 32 層、8 個 KV 頭、每頭 128 維、f16 的模型為例,8192 tokens 約 1 GiB,32768 tokens 約 4 GiB(示範計算)。

KV cache 是什麼?為什麼會佔顯存?

KV cache 是推論時為每個已處理的 token 暫存的注意力 key/value,讓模型不必每生成一個字就重算前面所有內容。它要為每一層、每個 KV 頭都存一份,所以上下文越長、層數越多,佔的顯存就越大。

Q4_K_M 一個權重平均用幾 bit?

llama.cpp 量化說明以 Llama-3.1-8B 為例,列出 Q4_K_M 的平均值是 4.8944 bits/weight,Q8_0 是 8.5008,F16 是 16.0005。這是以該模型為例的表,其他模型各層的量化組合不同,數字會略有差異,所以拿來估算要留餘裕。

要去哪裡查模型的層數和 KV 頭數?

這些數字寫在模型 GGUF 檔案的 metadata 裡。GGUF 規格定義了 block_count(層數)、attention.head_count、attention.head_count_kv(KV 頭數)等欄位;用能讀取 GGUF metadata 的工具就能查到,不需要自己猜。

留言

用 GitHub 帳號登入就能留言,留言會公開顯示在 GitHub Discussions。留言前請先看社群規則。

本地大模型