top of page

UGREEN DXP6800 Pro + Ollama 続編:64GB化したNASで qwen3-coder:30b は Sonnet の代わりになるのか?

  • takeshiohno
  • 1 日前
  • 読了時間: 11分

はじめに

前回の記事では、UGREEN DXP6800 Pro に eGPU 経由で RTX 2000 Ada を載せ、Ollama を Docker 上で動かし、さらに Zed からローカルLLMへ接続するところまでをまとめました。

前回時点での到達点はこうでした。

  • Ollama は ollama/ollama:0.24.0 に固定

  • NVIDIA Driver は 535.261.03

  • GPU は RTX 2000 Ada 16GB

  • qwen3:14b は 100% GPU で快適に動作

  • qwen3-coder:30b は本体RAM不足で本格検証できず

  • UGREEN DXP6800 Pro の本体RAMを 64GB に増設予定

今回はその続きです。

NAS本体のメモリを 8GB から 64GB に増設し、qwen3-coder:30b がどこまで実用になるのかを試しました。

さらに今回は単なるベンチマークだけではなく、実際に Zed 経由でローカルLLMを使い、Sonnet と qwen3-coder:30b に同じようなコーディング課題を投げて、成果物の質も比較してみました。

結論から言うと、

qwen3-coder:30b はローカルLLMとしてはかなり健闘する。ただし、Sonnet の代替というより「用途を絞れば実用的なローカル補助役」という位置づけ。

という感触です。

今回の構成

最終的な構成は以下です。

UGREEN DXP6800 Pro
 ├ RAM: 64GB DDR5 SODIMM
 ├ eGPU: RTX 2000 Ada Generation 16GB
 ├ NVIDIA Driver: 535.261.03
 ├ Docker
 │   ├ ollama: ollama/ollama:0.24.0
 │   └ open-webui: ghcr.io/open-webui/open-webui:main
 └ Zed から http://<NASのIP>:11434 で接続

Ollamaを 0.24.0 に固定している理由は前回と同じです。

Ollama v0.30系以降の新エンジンでは、この環境だと CUDA error: device kernel image is invalid が出て、モデルが起動できませんでした。ドライバーを上げる選択肢もありますが、今回は安定性を優先し、旧GGMLエンジンの 0.24.0 に固定しています。


まずハマった:コンテナ内だけ nvidia-smi が落ちる

RAM増設後、30Bの検証に進もうとしたところ、まず次の問題が出ました。

ホスト側では nvidia-smi が正常に通ります。

NVIDIA-SMI 535.261.03
Driver Version: 535.261.03
CUDA Version: 12.2

GPU: NVIDIA RTX 2000 Ada Generation
Memory: 0MiB / 16380MiB

ところが、Ollamaコンテナ内で実行するとこうなりました。

docker exec -it ollama nvidia-smi
Failed to initialize NVML: Unknown Error

ホストではGPUが見えているのに、Ollamaコンテナ内ではNVML初期化に失敗する状態です。

切り分けとして、CUDAテストコンテナを実行しました。

docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi

これは正常に通りました。

つまり、NVIDIAドライバーも NVIDIA Container Runtime も正常。問題は既存の ollama コンテナの作り方だけでした。

そこで、Ollamaコンテナを --gpus all 付きで作り直しました。

docker stop ollama
docker rm ollama

docker run -d \
  --name ollama \
  --gpus all \
  --network ai \
  -v ollama:/root/.ollama \
  -p 11434:11434 \
  --restart unless-stopped \
  ollama/ollama:0.24.0

作り直し後は、コンテナ内でも nvidia-smi が通るようになりました。

docker exec -it ollama nvidia-smi
NVIDIA-SMI 535.261.03
Driver Version: 535.261.03
CUDA Version: 12.2

ここでようやく、本当の意味で30BのGPUオフロード検証に進めます。

ベンチマーク結果

テストには自作の test.sh を使いました。

条件は以下です。

  • temperature: 0

  • seed: 42

  • T1: 短文生成 64 token

  • T2: 長文生成 768 token

  • 生成 tok/s と prompt処理 tok/s を計測

qwen3:14b

=== qwen3:14b (ctx=8192) ===
[T1] 生成 64tok @ 22 tok/s | prompt処理 544 tok/s | load 5308ms
[T2] 生成 768tok @ 22 tok/s | prompt処理 599 tok/s | load 123ms

14Bは前回同様、非常に安定しています。

ollama ps では 100% GPU。VRAM内に収まり、システムRAMをほぼ使わずに動きます。

qwen3-coder:30b

=== qwen3-coder:30b (ctx=16384) ===
[T1] 生成 21tok @ 24 tok/s | prompt処理 41 tok/s | load 8244ms
[T2] 生成 768tok @ 21 tok/s | prompt処理 51 tok/s | load 124ms

=== qwen3-coder:30b (ctx=32768) ===
[T1] 生成 21tok @ 22 tok/s | prompt処理 32 tok/s | load 8194ms
[T2] 生成 768tok @ 19 tok/s | prompt処理 41 tok/s | load 122ms

=== qwen3-coder:30b (ctx=65536) ===
[T1] 生成 21tok @ 20 tok/s | prompt処理 24 tok/s | load 7800ms
[T2] 生成 768tok @ 17 tok/s | prompt処理 31 tok/s | load 132ms

意外だったのは、生成速度だけを見ると30Bがかなり速いことです。

ctx 16k では 21〜24 tok/s、ctx 64k でも 17〜20 tok/s 出ています。

以前、GPU接続が壊れていた状態では 9〜11 tok/s 程度だったので、Ollamaコンテナを正しくGPU接続できるようにしたことで、30Bの生成速度はおよそ2倍になりました。


30BはどのくらいGPUに載っているのか

ctx 65536 で qwen3-coder:30b を起動した状態の ollama ps はこうでした。

NAME               SIZE     PROCESSOR          CONTEXT
qwen3-coder:30b    25 GB    36%/64% CPU/GPU    65536

nvidia-smi はこうです。

Memory-Usage: 15653MiB / 16380MiB
Process: /usr/bin/ollama 15648MiB

つまり、VRAM 16GBをほぼ使い切り、64%をGPU、36%をCPU側に逃がして動いています。

メモリ状況は以下でした。

Mem: 62Gi total / 15Gi used / 47Gi available
Swap: 37Gi total / 6.5Mi used

Swapは実質未使用です。

これはかなり良い状態です。

30Bを完全にGPUへ載せるにはVRAM 16GBでは足りませんが、64GB RAM化によってCPU/GPUオフロードが安定し、実用速度で動くようになりました。


ただし、Zed経由ではかなり遅く感じる

ここでベンチマークと実利用の差が出ました。

ベンチ上では qwen3-coder:30b は 17〜24 tok/s 出ています。数字だけ見ると、14Bと大差ないようにも見えます。

しかし、Zedから使うとかなり遅く感じます。

理由は prompt処理速度です。

qwen3:14b
prompt処理: 500〜600 tok/s

qwen3-coder:30b
prompt処理: 24〜51 tok/s

Zedは、選択範囲だけでなく、周辺コード、ファイル情報、ワークスペース文脈などをまとめてモデルに渡します。

そのため、体感速度を支配するのは「生成速度」よりも「入力を読む速さ」です。

30Bは回答を書き始めればそこそこ速いのですが、書き始めるまでが重い。Zed上では、ここがかなり目立ちます。

特に ctx 65536 のような大きいコンテキストでは、prompt処理が 24〜31 tok/s まで落ちます。

そのため、Zedの常用モデルとしては、30Bをそのまま使うより、16kや32kに絞った派生モデルを作る方が現実的です。

cat > Modelfile.qwen3-coder-zed <<'EOF'
FROM qwen3-coder:30b

PARAMETER num_ctx 16384
PARAMETER num_predict 2048
PARAMETER temperature 0.1
PARAMETER top_p 0.9

SYSTEM """
You are a concise coding assistant for Zed.
Answer in Japanese unless code-only is requested.
Prefer short, direct answers.
When asked to write code, output the code first.
Do not write long explanations unless explicitly requested.
"""
EOF

docker exec -i ollama ollama create qwen3-coder:zed -f - < Modelfile.qwen3-coder-zed

Sonnet と qwen3-coder:30b に同じ課題を投げてみる

次に、実際のコーディング課題で比較しました。

課題はこれです。

PowerShellでCSVでユーザ情報を取得し、AD上にユーザを作成するスクリプトを書いてください。

Sonnetにはこの短いプロンプトをそのまま投げました。

一方、qwen3-coder:30b には、出力が長くなりすぎないように、少し制約を付けたプロンプトを使いました。

PowerShellスクリプトだけを書いてください。説明は不要です。

要件:
- CSVをImport-Csvで読み込む
- CSV列: SamAccountName, GivenName, Surname, DisplayName, UserPrincipalName, Path, Password
- Active Directory上にユーザを作成する
- 既存ユーザがいる場合はスキップする
- 初回ログオン時にパスワード変更を要求する
- エラーはtry/catchでログ出力する
- 実行前確認用にWhatIf対応する

出力は以下だけ:
1. CSVサンプル
2. PowerShellスクリプト

長い解説、前提説明、注意事項は書かないでください。

この時点で、すでに少し条件が違います。

Sonnetは曖昧な依頼をどこまで補ってくれるか。qwenは明確な制約を与えたとき、どこまで実用コードを出せるか。

そういう比較です。


成果物比較:Sonnet版

Sonnet版は、かなり「業務スクリプト」寄りの成果物でした。

入っていた要素は以下です。

  • CSVファイル存在確認

  • 必須カラムチェック

  • Active Directory モジュール確認

  • OU存在確認

  • 既存ユーザー確認

  • 作成・更新・スキップ・失敗件数の集計

  • ログファイル出力

  • Manager設定

  • 終了コード

  • 実行結果サマリ

これはかなり実務寄りです。

ADユーザー作成のような操作は、失敗したときに「どの行で、なぜ失敗したか」が残らないと困ります。その意味で、Sonnet版は運用スクリプトとして必要な要素をかなり先回りして入れていました。

ただし、問題もありました。

一番大きいのは WhatIf の扱いです。

Sonnet版では、[CmdletBinding(SupportsShouldProcess)] を使いつつ、独自に [switch]$WhatIf も定義していました。

PowerShellでは SupportsShouldProcess を有効にすると、-WhatIf は共通パラメータとして提供されます。そのため、明示的に $WhatIf を定義するのは避けた方がよいです。

ここは修正必須です。

また、Sonnet版はCSVカラムが多めでした。

  • FirstName

  • LastName

  • DisplayName

  • SamAccountName

  • UserPrincipalName

  • Email

  • Department

  • Title

  • OU

  • Password

  • PasswordNeverExpires

  • AccountEnabled

  • Description

  • OfficePhone

  • Manager

実務的ではありますが、最初のサンプルとしては少し重い印象です。


成果物比較:qwen3-coder:30b版

qwen版は、かなり短く、プロンプトに素直なコードでした。

入っていた要素は以下です。

  • Import-Csv

  • Import-Module ActiveDirectory

  • New-ADUser

  • 既存ユーザーはスキップ

  • ChangePasswordAtLogon $true

  • 手動の WhatIf 対応

  • try/catch

最低限の要件にはきちんと沿っています。

特に、今回のプロンプトで指定した「説明不要」「コード中心」「既存ユーザーはスキップ」「初回ログオン時にパスワード変更」は守れていました。

一方で、本番投入には不足があります。

  • CSVファイル存在確認がない

  • 必須カラム検証がない

  • 空欄チェックがない

  • OU/Pathの存在確認がない

  • ログファイル出力が弱い

  • 成功/失敗件数のサマリがない

  • パスワードポリシー違反時の扱いが弱い

  • ADコマンドのフィルタ指定に改善余地がある

つまり、qwen版は「サンプルとしては良いが、そのまま業務利用するには薄い」という評価です。

採点してみる

今回の成果物を、実用性・安全性・保守性でざっくり採点するとこうです。

モデル

点数

コメント

Sonnet

78点

業務向けの構成は良い。ただし WhatIf 実装とカラム過多が減点。

qwen3-coder:30b

62点

プロンプトには素直。短くて読みやすいが、AD運用スクリプトとしては検証・ログ・安全性が不足。

Sonnetは「曖昧な依頼から実務に必要なものを補う」のが得意です。qwenは「明確に指定された要件を短くコード化する」のはできますが、実務上の事故防止策を自発的に盛る力はSonnetより弱い印象でした。


速度面の比較

品質以前に、Zed経由での体感差は大きいです。

Sonnetはクラウドモデルなので、手元のNASのprompt処理速度やVRAM制約を受けません。一方、qwen3-coder:30b はローカルで動いているので、入力が大きくなると素直に遅くなります。

今回のようなPowerShellスクリプト生成でも、qwen3-coder:30b は「終わる感じがしない」ように見えました。

これは生成速度そのものよりも、

  • Zedが送るシステムプロンプト

  • ワークスペース文脈

  • 大きめのコンテキスト設定

  • 30Bのprompt処理の遅さ

  • qwen系の長文化傾向

が組み合わさった結果だと思います。

ローカルLLMをZedで使う場合、モデルの性能だけでなく、「どのくらい入力を送るか」が体感速度を大きく左右します。


Zedでの使い分け

今回の検証後、Zedでは以下の運用がよさそうだと感じました。

普段使い

qwen3:14b

14Bは 100% GPU で動き、prompt処理が非常に速いです。

ちょっとしたコード説明、短い修正、コマンド生成、設定ファイルの確認なら、14Bの方が快適です。

品質優先のローカルコード生成

qwen3-coder:zed

30Bをそのまま使うのではなく、num_ctx 16384、num_predict 2048 程度に制限したZed用モデルを作るのがよさそうです。

64kコンテキストは夢がありますが、Zed常用には重いです。

複雑な設計・本番投入前レビュー

Sonnet

実務で事故ると困るスクリプトや、要件が曖昧な相談は、まだSonnetの方が安心です。

特にAD、Microsoft 365、Azure、セキュリティ、権限まわりのようなテーマでは、クラウドモデルの方が先回り力が高いと感じました。


qwen3-coder:30b をうまく使うプロンプト

qwen3-coder:30b は、曖昧な依頼を丸投げするより、出力条件を強く指定した方が良いです。

悪い例:

PowerShellでCSVでユーザ情報を取得し、AD上にユーザを作成するスクリプトを書いてください。

この依頼だと、モデルがどこまで説明するか、どのカラムを想定するか、ログやWhatIfを入れるかが曖昧です。

良い例:

PowerShellスクリプトだけを書いてください。説明は不要です。

要件:
- CSVをImport-Csvで読み込む
- CSV列: SamAccountName, GivenName, Surname, DisplayName, UserPrincipalName, Path, Password
- Active Directory上にユーザを作成する
- 既存ユーザがいる場合はスキップする
- 初回ログオン時にパスワード変更を要求する
- エラーはtry/catchでログ出力する
- 実行前確認用にWhatIf対応する

出力は以下だけ:
1. CSVサンプル
2. PowerShellスクリプト

長い解説、前提説明、注意事項は書かないでください。

さらに短くしたい場合はこうです。

PowerShellコードだけ出してください。
説明不要。
CSV列は SamAccountName,GivenName,Surname,DisplayName,UserPrincipalName,Path,Password。
Import-Csvで読み込み、New-ADUserでユーザ作成。
既存ユーザはスキップ。
ChangePasswordAtLogonはtrue。
try/catchでエラー処理。
WhatIf対応。
コードブロック1つだけ。

ローカルLLMは、プロンプトで「どこまで書くか」を明示するとかなり扱いやすくなります。


今回の結論

64GB RAM化により、UGREEN DXP6800 Pro + RTX 2000 Ada 16GB の構成で qwen3-coder:30b は実用速度で動くようになりました。

特に、ctx 65536でも 17〜20 tok/s 出ているのはかなり良い結果です。

qwen3-coder:30b
- ctx 16384: 21〜24 tok/s
- ctx 32768: 19〜22 tok/s
- ctx 65536: 17〜20 tok/s
- 36% CPU / 64% GPU
- VRAM 約15.6GB使用
- Swapほぼ未使用

ただし、Zed経由での体感はベンチほど軽くありません。

理由は、30Bのprompt処理が遅く、Zedが大量の文脈を送ると初動がかなり重くなるからです。

Sonnetとの比較では、qwen3-coder:30b は短いコード生成には十分使えます。しかし、曖昧な依頼を実務レベルの成果物に仕上げる力は、まだSonnetの方が上です。

今回の私なりの結論はこうです。

qwen3:14b
→ Zed常用の軽快モデル

qwen3-coder:30b
→ ローカルで品質を少し上げたいときのコード生成モデル

Sonnet
→ 実務投入前提・曖昧な要件・設計相談・レビュー向け

ローカルLLMは、クラウドLLMを完全に置き換えるものではありません。ただし、NAS上で常時動かせて、Zedから直接呼べて、コード生成や軽い相談に使えるというだけでも十分に価値があります。

何より、手元のUGREEN DXP6800 Proが、ストレージだけでなくローカルAI開発環境としても使えるようになったのはかなり面白いです。

前回は「30Bはメモリ増設後の宿題」で終わりました。今回、その宿題にはひとまず答えが出ました。

30Bは動きます。ただし、快適に使うにはモデル選びとプロンプト設計が必要です。

次は、Zed用に qwen3-coder:zed のような軽量設定モデルを作り、実際のプロジェクトでどこまで使えるかを継続して試してみます。

最新記事

すべて表示
(続き)UGREEN DXP6800 Pro で Ollama を動かす — CUDAエラー地獄と、Zed からのローカルコーディング接続まで

はじめに 前回、UGREEN DXP6800 Pro に eGPU 経由で RTX 2000 Ada を載せ、Docker から --gpus all でGPUを叩けるところまで持っていきました。今回はその続きで、本来の目的だった ローカルLLMをコーディングに使うところまでの記録です。 ゴールはこんな感じ: NAS本体で Ollama を常時稼働させる ブラウザからは Open WebUI で叩

 
 
 
Copilot の「Cowork」、自分のアプリから呼べるの? 調べたら課金の罠まで出てきた話

Microsoft 365 Copilot に「Cowork」っていう自律エージェントが乗ってきました。中身は Anthropic の Claude。メール送ったり予定入れたり資料作ったり、指示するだけで勝手に動いてくれるやつです。すごい。 で、自社サービスに AI アシスタントを積んでる身としては当然こう思うわけです。「これ、自分のアプリから呼べたら最高では?」 結論から言うと…呼べませんでした

 
 
 

コメント


bottom of page