ローカルLLM

概要

  • 2026-08 100 万円くらいの GPU で Qwen 3.8 27B が 150 tok/s くらいの速度で動く。SLM (Small Language Model) と言われるもので、パソコンで動くもの。Opus 4.8 Low に匹敵する性能、3 倍速(Qwen 3.8 は Overthinking なのでよりよいとは思わないけど)
    • Qwen 3.8 27B、ローカルで動く小さいモデルなのに DeepSeek V4 Flash 0731 (294B) 並の知能が出てる点で、2026-08 時点で明らかなブレークスルー。Artificial Analysis によると Sonnet 4.6 Max より頭いいらしい。
  • llm-jp-4-33b-thinking が 2026-08 に出て、日本語能力が gpt-4o 級で実用水準になったものの、数学とかコーディングとかエージェントについてはそもそもターゲットに入れていないという雰囲気を感じます。DeepSWE などのベンチは公開されてすらいない。
    • 2025 年秋から学習開始し 2026-08 に公開、なので、そもそもコーディングエージェント系の知見が学習開始時点でなさそうです。
    • 超計算資源不足でベストを尽くしているようなので、そちらは頑張っていただきたいのですが、それとは別に llm-jp のモデルを使う必要性はライセンスの問題などを除けば性能的にはない (2026-08 にリリースされた Qwen 3.8 を使えばよい)。
    • llm-jp コミュニティで大事そうな人 Odashi, kodama26985649, kwashizzz, Bluecode.net

環境

以下数値例はすべてこの環境を前提

項目値
GPUNVIDIA GeForce RTX 3070 Ti
GPU のメモリ8 GB
システムメモリ94 GB
CPUIntel Core i9-11900K(16スレッド)
OSUbuntu

目次

1. パラメータとは何か

言語モデルは、大量の数値の集まりである。この数値ひとつひとつを パラメータ と呼ぶ。

パラメータは学習によって決まる。学習前は乱数が入っており、大量の文章を読ませる過程で少しずつ調整され、最終的に「この単語の次にはこの単語が来やすい」という知識を担う値に落ち着く。学習が終わったパラメータの集合を 重み と呼ぶ。重みとパラメータはほぼ同じ意味で使われる。

パラメータの個数がモデルの規模を表す。個数が多いほど複雑な知識を蓄えられるが、その分だけ記憶領域を消費する。

B という単位

モデル名によく現れる 8B 30B 2.4T は、パラメータの個数である。

表記読み個数
8B8 billion80億
30B30 billion300億
70B70 billion700億
2.4T2.4 trillion2兆4000億

B は billion(10億)、T は trillion(1兆)の頭文字である。

トークンという単位

モデルは文章を1文字ずつでも1単語ずつでもなく、トークンという単位で扱う。トークンは「よく現れる文字のかたまり」で、英語なら単語かその一部、日本語なら1〜2文字程度が1トークンになることが多い。

以降、文章の長さも生成の速さも、すべてトークンで数える。

  • 「コンテキスト長 32768」= 一度に 32,768 トークンまで扱える
  • 「12 トークン/秒」= 1秒に 12 個のトークンを生成する

モデルが1回の処理で行うのは、次の1トークンを決めることである。 文章はこれを繰り返して作られる。

2種類のメモリ — VRAM とシステムRAM

計算に入る前に、メモリが2種類あることを押さえる必要がある。この区別が、以降のすべての判断の土台になる。

VRAMシステムRAM
正式名称Video RAM(ビデオメモリ)メインメモリ
どこにあるかGPU の基板上マザーボード上
誰が使うかGPUCPU
この環境の容量8 GB94 GB
読み出し速度約 608 GB/秒約 50 GB/秒
増やせるか不可(GPUごと交換)可(メモリを挿す)

VRAM とは、GPU が直接読み書きできる専用メモリである。パソコンを組むときに挿すメモリ(システムRAM)とは物理的に別の部品で、グラフィックボードに最初から載っている。だから容量は買った時点で決まり、後から増やせない。

読み出し速度が 12倍違う 点が決定的である。この差が、ローカルLLMの速度をほぼ単独で決める。

なぜ GPU 専用のメモリが必要なのかというと、GPU は数千個の演算器を同時に動かすため、CPU 用のメモリでは供給が追いつかないからである。そこで GPU の隣に高速なメモリを直結している。その代償として容量が小さい。

物理的な配置を図にする。

Loading diagram...

図の読み方。CPU とシステムRAM、GPU と VRAM が、それぞれ別々に直結している。2つの島の間は PCI Express という通路でつながっているが、ここは VRAM の直結より20倍以上遅い。

だから「VRAM に入りきらない分をその都度 PCI Express 経由で送る」という方式は成立しない。実際 llama.cpp はそれをせず、どちらの島に置くかを起動時に決めて固定する。RAM 側に置かれた重みは CPU が計算し、VRAM 側の重みは GPU が計算する。往復するのは計算の途中結果だけで、これは数KBしかない。

「GPU に載る」とは何を意味するか

以降この文書で 「GPU に載る」 と書いたら、そのデータが VRAM に収まっているという意味である。

  • VRAM に収まる → GPU が 608 GB/秒で読める → 速い
  • VRAM に収まらない → システムRAM に置いて 50 GB/秒で読む → 遅い

現在の状態を確認するコマンドは次のとおり。

nvidia-smi --query-gpu=name,memory.total,memory.used,memory.free --format=csv

この環境での実行結果である。

NVIDIA GeForce RTX 3070 Ti, 8192 MiB, 3517 MiB, 4423 MiB

左から順に、GPU名・VRAM総量(8 GB)・使用中(3.5 GB)・空き(4.4 GB)である。

判断の軸は2つある。動かせるかどうかはシステムRAM の容量で決まり、速いかどうかは VRAM の容量で決まる。 第5章でその計算方法を示す。

必要なメモリの計算

パラメータ1個あたり何バイトで記録するかが決まれば、必要なメモリは掛け算で出る。

学習時の標準的な形式は BF16 で、これは1個あたり2バイトを使う。したがって、

30B のモデルを BF16 で保持する場合
  300億個 × 2バイト = 600億バイト = 約 60 GB

この60GBを、モデルを動かしている間ずっとメモリ上に置いておく必要がある。GPUのメモリが8GBしかない環境では、当然入らない。

この問題を解決するのが次章の量子化である。


2. 量子化 — なぜ小さくできるのか

量子化 とは、パラメータを記録する精度を落として、容量を減らす操作である。

BF16 の2バイト(16ビット)を4ビットに落とせば、容量は4分の1になる。ただし4ビットで表せるのは16通りの値だけである。もともと連続的な数値だったものを16段階に押し込めることになる。

なぜそんな乱暴なことが成立するのか。素朴にやると失敗する例から見る。

素朴な方法は失敗する

パラメータの実際の値は、たとえばこのような小さな数値の並びである。

0.0231, -0.0187, 0.0142, -0.0203, 0.0119, ...

ここで「-1.0 から +1.0 までを16段階に区切る」という素朴な方法を取ると、目盛りの間隔は 2.0 ÷ 16 = 0.125 になる。各値を最も近い目盛りに丸めると、

0.0231  → 0
-0.0187 → 0
0.0142  → 0

すべてゼロになる。値の違いが完全に消え、モデルは機能しなくなる。目盛りが粗すぎるためである。

ブロック単位のスケーリング

そこで実際の量子化は次のようにする。

パラメータを32個ずつの塊に区切る。この塊を ブロック と呼ぶ。そしてブロックごとに、そのブロックに含まれる値の範囲を調べる。

上の例のブロックでは、絶対値の最大が 0.0231 だった。ならば「-0.0231 から +0.0231 までを16段階」で区切ればよい。目盛りの間隔は 0.0462 ÷ 16 ≒ 0.003 になる。

0.0231  → 0.0231   (目盛り 15)
-0.0187 → -0.0185  (目盛り 3)
0.0142  → 0.0139   (目盛り 12)

値の違いが保たれている。

このとき「このブロックは 0.0231 を基準にした」という情報を、ブロックごとに1個だけ別に保存する。この基準値を スケール係数 と呼ぶ。使うときは「目盛り番号 × スケール係数」で元の値に近い数を復元する。

追加で保存するのは32個につきスケール係数1個だけなので、容量の増加はごくわずかである。それでいて、値が小さくまとまっている場所では細かい目盛りを、値が大きい場所では粗い目盛りを、それぞれ自動的に使い分けられる。

一言でいえば、全体を1本の物差しで測るのをやめ、32個ごとにその範囲にぴったり合った物差しを使い分ける。これが量子化が成立する理由である。

ファイル名の読み方

量子化されたモデルのファイルには、Q4_K_M のような記号が付く。分解すると次の意味になる。

部分意味
Q4パラメータ1個を4ビットで記録する
Q5 Q8それぞれ5ビット、8ビット
_KK-quants。ブロック単位スケーリングの改良版
_S _M _LSmall / Medium / Large。同じビット数でも、重要な層により多くのビットを配分する度合い
IQI-quants。後述の重要度行列を使った方式

重要度行列(importance matrix、略して imatrix)とは、実際の文章をモデルに流して「どのパラメータがよく使われるか」を測定したものである。よく使われるパラメータには精度を厚く配分することで、同じ容量でも品質を保ちやすくなる。

Q4_K_M が標準的な選択肢である。後述の llama.cpp も、指定がなければ Q4_K_M を取得しようとする。

量子化後の容量

パラメータ1個あたりのバイト数が変わるだけなので、計算は簡単である。

ここで注意すべき点がある。Q4 という名前は「4ビット」だが、実際の保存コストは4ビットより大きい。

理由は前節の仕組みそのものにある。量子化した値(4ビット)に加えて、ブロックごとのスケール係数を保存する必要があるためである。さらに llama.cpp は、出力に強く効くテンソルを自動的に Q6_K(6ビット)に格上げする。

llama.cpp の公式資料は Q4_K_M の実際のコストを 4.8944 bpw(bits per weight、1パラメータあたりのビット数)と記載している。実装のコメントにも // Effectively 4.5 bits per weight とある。

したがって実際の計算はこうなる。

形式実際の1個あたり30B の場合
BF16(元の形式)2 バイト60 GB
Q8_0(8ビット)約 1.06 バイト32 GB
Q4_K_M約 0.61 バイト約 18 GB

Q4 なら「Bの数字に 0.6 を掛けるとGB」 という覚え方になる。

モデルQ4_K_M での概算
8B約 5 GB
30B約 18 GB
70B約 43 GB
2.4T(=2400B)約 1,460 GB

最後の行が、2.4T のモデルを個人の環境で動かせない理由である。1.4テラバイトを超えるメモリが必要になる。

なお、この 0.6 という係数は目安である。第8章に実測したファイルサイズの一覧があるので、実際に動かす前にはそちらを確認すること。


3. 量子化で何が失われるか

容量が4分の1になるなら、何かを失っているはずである。何をどう失うのかを正確に理解しておかないと、実務で判断を誤る。

モデルは確率で単語を選んでいる

前提として、言語モデルの動作を確認する。

「東京は日本の___」という入力に対して、モデルは内部で次の単語の候補に確率を割り当てる。

首都   75%
中心   12%
都市    8%
(以下略)

そして最も確率の高いものを選ぶ。この確率の計算にパラメータを使うので、パラメータを丸めると確率がわずかにずれる。

ずれ方には偏りがある

llama.cpp には、量子化の前後で出力の確率分布がどれだけ変わるかを測る機能がある(llama-perplexity --kl-divergence)。Llama 3 8B を Q4_K_M にしたときの出力である。

指標値意味
Mean Δp-0.024%正解トークンに与える確率の平均変化。わずかに下がる
RMS Δp5.519%同じ変化の二乗平均。1トークンあたりの典型的なずれの大きさ
Same top p91.9%量子化前と最も確率の高いトークンが一致した割合

Δp とは、正解のトークンに与えられた確率の「量子化後 − 量子化前」である。符号付きなので、上がった場合と下がった場合が打ち消し合う。

読み方は2つある。

平均はほぼゼロだが、典型的なずれはゼロではない。 平均が -0.024% なのは打ち消し合った結果であって、1トークンごとのずれが小さいという意味ではない。打ち消し合わないよう二乗して測った RMS は 5.519%、平均の 230 倍ある。

8.1% のトークンで、選ばれるトークンそのものが変わる。 Same top p が 91.9% なので、残り 8.1% では量子化前と違うトークンが1位になっている。なおこの指標が見ているのは「1位が一致したか」だけで、入れ替わった先が元の2位だったかは測っていない。

選ばれるトークンが変わるのは、どういう場面か。「首都 75%、中心 12%」のように大差がついている場面では、確率が多少ずれても順位は変わらない。しかし、

選択肢A  34%
選択肢B  33%

このように僅差の場面では、0.5% ずれただけで逆転する。

つまり、もともと僅差だった判断だけが、ひっくり返る。平均的な誤差はほぼゼロなのに、一部が壊れているのはこのためである。

僅差の場面とは、モデルが迷っている場面

では、モデルが僅差になるのはどういうときか。難しい問題を解いているときである。簡単な問題ならモデルは確信を持って答えられるが、難しい問題では複数の候補が拮抗する。

この予測は実測と一致する。同じモデル・同じタスクで、量子化の方式だけを変えて測った結果がある。出典は arXiv:2504.04823(COLM 2025)Table 1、DeepSeek-R1-Distill-Qwen-32B。

設定何を4ビットにしたかAIME-120(難)MATH-500(中)GSM8K(易)5指標平均
BF16(元)—61.796.394.2—
W4A16 / AWQ重みだけ63.6(+1.9)95.9(-0.4)94.4(+0.2)-0.4
W4A16 / GPTQ重みだけ57.5(-4.2)95.9(-0.4)94.3(+0.1)-1.9
W4A4KV4 / FlatQuant重み+活性値+KVキャッシュ57.8(-3.9)95.1(-1.2)94.2(0.0)-2.9

llama.cpp の Q4_K_M は「重みだけ」を4ビットにする方式である。したがって対応するのは W4A16 の2行であり、最下行の W4A4KV4 ではない。論文の要旨もこう述べている。

lossless quantization can be achieved with W8A8 or W4A16 quantization, lower bit-widths introduce significant accuracy risks

(W8A8 または W4A16 なら無損失の量子化が達成できる。それより低いビット幅は重大な精度リスクを生む)

まず押さえるべきは、weight-only の4ビットは平均では実質無損失だということである。 「4ビットにすると賢さが落ちる」という素朴な理解は正しくない。

そのうえで W4A16 の2行を見比べる。同じ4ビット weight-only でも、アルゴリズムが違うだけで AIME は +1.9 にも -4.2 にもなる。一方 GSM8K はどちらも ±0.1 に収まっている。平均は無損失でも、難しいタスクだけが大きく振れる。 論文もこれを主要な発見として挙げている。

Harder tasks (e.g., AIME-120) suffer up to 4× greater degradation than simpler ones (e.g., GSM8K).

(難しいタスクは、簡単なタスクの最大4倍の劣化を被る)

機序を直接述べた研究もある。arXiv:2405.00632(NAACL 2024 Findings)より。

quantization disproportionately affects samples where the full model exhibited low confidence levels in the first place.

(量子化は、元のモデルが最初から自信の低かったサンプルに不釣り合いに影響する)

一言でまとめると、量子化は、モデルが迷っていた答えから先に奪う。

実務上の危険