VRAM 20 GB の Radeon で、社内の文章の下書きをローカル LLM に任せられるかを技術検証しました。20 GB だと、120B 級の MoE は一部をメインメモリに逃がさないと動かず、27B 級の密なモデルは量子化すれば丸ごと載ります。どちらを選ぶかで迷うところなので、llama.cpp で速さと VRAM を測り、下書きを作る手順にも通して比べました。
結論
- Qwen3.8-27B を Q4_K_M にすると 16.8 GB で、文脈 32768 と合わせて VRAM 20 GB に全部載ります。 生成は 31.6 トークン/秒でした。
- GPT-OSS Swallow 120B(MXFP4、61.3 GB)は載らないので、
--n-cpu-moe 30で専門家の一部をメインメモリに置きました。生成は 7.9 トークン/秒で、Qwen3.8-27B の約 1/4 です。 - 作り直した同じ下書きの手順で、Qwen3.8-27B は約 29 分で3件とも検査を通り、Swallow は約 58 分で3件中2件でした。この比べ方では、Qwen3.8-27B が速さでも検査を通った数でも上回りました。
- 推論の深さは要求の
chat_template_kwargs.reasoning_effortで渡します。Qwen3.8 が受けるのはxhigh(既定)・medium・lowで、gpt-oss のhighは通りません。
試した環境
- GPU: Radeon RX 7900 XT(gfx1100、VRAM 20 GB)
- OS など: Ubuntu、ROCm 7.2.4
- 推論: llama.cpp v0.6.0 を HIP でビルドした llama-server
- 重み: 公式の配布物を取り、自分で GGUF に変換(第三者が配っている GGUF は使っていません)
比べたのは次の2つです。
- GPT-OSS Swallow 120B RL v0.1(MXFP4): 東京科学大学の Swallow チームが gpt-oss を日本語向けに鍛え直したもの。117B の MoE で、1語ごとに使うのは約 5B です。
- Qwen3.8-27B: 27B の密なモデル。線形注意(Gated DeltaNet)の層3つごとに、通常の注意の層が1つ入る作りです。
重みのライセンスは、どちらも Apache-2.0 です(執筆時点のモデルカードの記載)。
ビルドと変換
llama.cpp は v0.6.0 を HIP でビルドしました。CPU だけで約2分(366 段)です。量子化に使う llama-quantize は、あとから足してビルドしました(4 段・数十秒)。
git clone --branch v0.6.0 --depth 1 https://github.com/ggml-org/llama.cpp llama.cpp
export PATH=/opt/rocm/bin:/opt/rocm/llvm/bin:$PATH ROCM_PATH=/opt/rocm HIP_PATH=/opt/rocm
cmake -S llama.cpp -B llama.cpp/build-hip -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DGGML_HIP=ON -DGPU_TARGETS=gfx1100 \
-DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_PREFIX_PATH=/opt/rocm \
-DLLAMA_CURL=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF
cmake --build llama.cpp/build-hip --target llama-server llama-cli -j 16
cmake --build llama.cpp/build-hip --target llama-quantize -j 8
GGUF への変換には、llama.cpp の requirements/requirements-convert_hf_to_gguf.txt だけを入れた venv を別に作りました(1.1 GB。torch は CPU 版 2.11.0)。変換はどちらのモデルも GPU を使いません。
Qwen3.8-27B は、v0.6.0 の変換器が Qwen3_5ForConditionalGeneration に対応していて、そのまま通りました。いったん BF16 の GGUF にしてから Q4_K_M に量子化します。
python llama.cpp/convert_hf_to_gguf.py "$SNAPSHOT" --outtype bf16 --outfile Qwen3.8-27B-BF16.gguf # 2 分 49 秒
llama.cpp/build-hip/bin/llama-quantize Qwen3.8-27B-BF16.gguf Qwen3.8-27B-Q4_K_M.gguf Q4_K_M 16 # 2 分 41 秒
rm Qwen3.8-27B-BF16.gguf # 途中の BF16 は 55 GB。量子化を変えたいときは作り直す
python は変換用の venv の物、$SNAPSHOT はダウンロードした重みの置き場です。量子化は imatrix なしの Q4_K_M(4.92 BPW)で、16.8 GB(15.6 GiB)になりました。画像も入力できるモデルですが、使わないので mmproj は作っていません。
Swallow は、そのままでは変換器が assert で落ちました。MoE のブロックの形が元の gpt-oss と違うためで、読み出しのときに形を戻すラッパーを通して変換しました(4 分 58 秒、RSS 4.9 GiB)。できた GGUF は、専門家が MXFP4、ほかが bf16 の 61.3 GB(57 GiB)です。
起こし方とサンプリング
Qwen3.8-27B は全部の層を GPU に載せます。
llama-server -m Qwen3.8-27B-Q4_K_M.gguf \
--host 127.0.0.1 --port 8080 -c 32768 -ngl 999 -fa on --jinja -t 16 --parallel 1
Swallow は 20 GB に収まらないので、--n-cpu-moe 30 を足して専門家の一部をメインメモリに置きます。
llama-server -m GPT-OSS-Swallow-120B-RL-v0.1-MXFP4_MOE.gguf \
--host 127.0.0.1 --port 8080 -c 32768 -ngl 999 --n-cpu-moe 30 -fa on --jinja -t 16 --parallel 1
サンプリングは、どちらもモデルカードの推奨に合わせました。Swallow は temperature 0.6・top_p 0.95・推論 medium、Qwen3.8 の考える版は temperature 1.0・top_p 0.95・top_k 20・min_p 0 です。
推論の深さは、OpenAI 互換の要求の本文に chat_template_kwargs.reasoning_effort を入れて渡します。
{"chat_template_kwargs": {"reasoning_effort": "medium"}}
迷いやすいのは値の名前です。gpt-oss 系と同じつもりで high を渡しても、Qwen3.8 では通りません。Qwen3.8 が受けるのは xhigh(既定)・medium・low です。
測った値
どちらも文脈 32768 で測りました。
| GPT-OSS Swallow 120B | Qwen3.8-27B | |
|---|---|---|
| GGUF | 専門家は MXFP4、ほかは bf16。61.3 GB | Q4_K_M。16.8 GB |
| 載せ方 | 専門家の一部をメインメモリ(--n-cpu-moe 30) | 全部 GPU(-ngl 999) |
| VRAM | 15.6 GB | 17.8 GB |
| 読み込み | 53 秒(ページキャッシュに載った後) | 約 13 秒 |
| 生成 | 7.9 トークン/秒 | 31.6 トークン/秒 |
| プロンプトの処理 | 短い入力で 17、5,600 トークンで 169 トークン/秒 | 約 800 トークン/秒 |
120B の MoE は 20 GB に載らないので専門家をメインメモリに逃がしましたが、その形では生成の速さが 27B の約 1/4 になりました。
Swallow は、短い入力ほどプロンプトの処理が遅くなりました。短い入力では 17 トークン/秒、5,600 トークンの入力では 169 トークン/秒です。専門家の重みを GPU に送る固定費が効いているのではないかと見ていますが、確かめてはいません。
VRAM は Swallow のほうが 15.6 GB で余りがあり、--n-cpu-moe は 27 前後まで下げられる見込みです。これも試していません。
下書きの手順で比べる
速さだけでは下書きに使えるかが分からないので、下書きを作る手順にも通して試しました。1回分は、LLM に十数回問い合わせて3件の下書きを作る手順です。できた下書きは、コードで書いた検査に通します。
Swallow で最初に回した手順では、約 20 分で3件とも検査を通りました。ところが推論を high にし、プロンプトを足した2回目は約 31 分かかり、検査を通ったのは6件中1件でした。入力の取り違えや、存在しない参照先が出ています。

そこで手順のほうを作り直しました。1件ずつ扱い、出力を JSON スキーマで縛る形です。この作り直した同じ手順で、2つのモデルを比べました。
- Swallow: 約 58 分。3件中2件が検査を通った
- Qwen3.8-27B: 約 29 分。3件とも通った。いちばん長くかかった段は、推論 xhigh で約 1.4 万トークンを出して 8 分かかった
遅く、検査を通る数も少なかったので、Swallow は落とし、重みも GGUF も消しました。
確かめていないこと
- Swallow の
--n-cpu-moeを 27 前後まで下げられるか、下げたときの速さ - Qwen3.8-27B の量子化の段(Q5・Q6 など)や、imatrix 付きとの質の差
- Swallow で短い入力が遅い原因(上の見立てのまま)
- 下書きの手順を何回も回したときの、検査を通る割合の差
おわりに
VRAM 20 GB では、120B の MoE を専門家をメインメモリに逃がして動かすより、27B の密なモデルを Q4_K_M で丸ごと載せるほうが、作り直した同じ下書きの手順で1回ずつ(各3件)比べたところ速く、検査を通った数も多くなりました(Qwen3.8-27B は3件とも、Swallow は3件中2件)。同じくらいの VRAM でモデル選びに迷っている方の目安になればうれしいです。
※ llama.cpp の変換器と llama-server の振る舞い、モデルカードの推奨の設定、ライセンスの記載は執筆時点の情報で、いまは変わっている可能性があります。


