1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Strata検証②:EVO-X2(Ryzen AI Max+ 395)で256K コンテクストが安定動作!Qwen3.8-Flash-Next × OpenCode でAIエージェント開発

1
Posted at

Strata検証②:EVO-X2(Ryzen AI Max+ 395)で256K コンテクストが安定動作! Qwen3.8-Flash-Next × OpenCode でAIエージェント開発

はじめに

前回の記事「EVO-X2(Ryzen AI Max+ 395)+ Vulkan で Qwen3.8-Flash-Next が動いた! でもコンテクスト長を大きくすると不安定!残念!」では、llama.cpp(Vulkan)で Qwen3.8-Flash-Next を 256K コンテクストで動かしたところ、10 万トークン前後の生成中に EVO-X2 がリセットしました。そのため、Flash-Next の常用は DGX Spark に移しました。

その直後、Qwen3.8-Flash-Next 専用の推論エンジン Strata が v0.1.40 で Ryzen AI Max+ 395(Strix Halo)に正式対応しました。そこで、同じ EVO-X2、同じ BIOS 設定とメモリの配分のまま、エンジンだけを Strata に替えて 256K を試しました。

結論

  1. Strata なら、EVO-X2 で 256K(262,144 トークン)のコンテクストが動いた。 速度などの測定も含めて約 10.6 時間動かし続け(うち GPU 使用率 95% 以上が約 8.2 時間)、リセットは 0 回でした。前回リセットが起きた「10 万トークン前後で生成中」の状況も通過し、最大コンテクストは約 23.7 万トークンでした。
  2. ハーネスの OpenCode と組み合わせて、256K のまま実際のエージェントとして使えた。 OpenCode V1(1.18.35)と V2(2.0.24)の両方で、ツールの呼び出し、思考、コンテクストの要約(compaction)、2 本同時の実行(Strata の "parallel": 2)まで確かめました。
  3. 速度も上がった。 1 件ずつの出力速度は、MTP(モデルに付いている投機デコード用の層)ありで 43.6 tok/s、MTP なしで 28.5 tok/s です(前回の llama.cpp は 20.4 tok/s)。長いプロンプトの読み込みは、前回の約 3〜4.5 倍の速さでした。
  4. 日本語の品質は変わらない。 JamC-QA(300 問)で 66.0%(前回の llama.cpp は 66.67%)。
  5. ただし、前回のリセットの原因は分かっていない。 「Strata にしたから直った」とは言えません。くわしくは「前回のリセットについて」の節に書きました。

構成

図 0 構成図

項目 内容
本体 GMKtec EVO-X2(Ryzen AI Max+ 395、メモリ 128GB)
GPU Radeon 8060S Graphics(Ryzen AI Max+ 395 の内蔵 GPU)
メモリの配分 前回と同じ。BIOS で VRAM に 96GB、残りがシステム RAM(OS から使えるのは約 30GB)
BIOS 1.09(2025-09-13)。GMKtec の公開ページに新しい BIOS は見当たらなかった
OS/カーネル Ubuntu 26.04 LTS / Linux 7.0.0-38(前回のリセットは 7.0.0-34 のとき)
推論エンジン Strata v0.1.40.2
ROCm AMD TheRock 7.14.1(Ryzen AI Max+ 395 向け)。ユーザー領域に展開し、システムの ROCm には触れていない
モデル Qwen3.8-Flash-Next(unsloth の GGUF、UD-IQ4_XS)。前回と同じファイル
クライアント OpenCode とベンチマークは、EVO-X2 とは別の PC から LAN 越しにつないだ

推論をする機械の上では推論だけを動かし、OpenCode などのハーネスは別の PC に置いています。推論機が固まったときに、記録やクライアントを道連れにしないためです。監視の記録を別の PC にも送っているのは、前回のリセットで直前の記録ごと消えてしまった反省からです。

Strata とは

Strata は Qwen3.8-Flash-Next 専用の推論エンジンです。MoE(Mixture of Experts)モデルのエキスパートのうち、よく使うものを GPU に、それ以外を CPU のメモリに置くことで、12GB 程度のゲーミング GPU でも 125B のモデルを動かせることで話題になりました。OpenAI 互換と Anthropic 互換の API を出すので、OpenCode などからそのままつなげます。

v0.1.40 で Ryzen AI Max+ 395 に対応し、ROCm(HIP)で動くようになりました。前回の llama.cpp は Vulkan で動かしていたので、GPU を動かす仕組みそのものが違うことになります。

ちなみに、Strata の開発者のマシンも Ryzen AI Max+ 395・128GB・Ubuntu 26.04 で、EVO-X2 とよく似ています。ただしメモリの配分は逆で、開発者は GPU のメモリ割り当てを小さくし、システム RAM 側を広げる構成です。

動かすときのコツ 1:EVO-X2 の配分では、既定のままだと黙って落ちる

Strata の既定(--expert-cache auto)は、全エキスパート(約 59.5GB)をシステム RAM 側に確保しようとします。当ラボの EVO-X2 は BIOS で VRAM に 96GB を割り当てているため、システム RAM は約 30GB しかなく、確保できずにエラー表示なしでエンジンが終了しました。ログの最後に残っていたのは次の 1 行です。

ArenaExpertSource: the arena could not be reserved (59523276800 B)

次の 2 つを明示すると解決しました。

--mmap-experts --expert-cache 24576

--mmap-experts は GGUF をファイルのまま対応づけて読む指定、--expert-cache 24576 は全エキスパート分の枠を取る指定です。これで全 24,576 エキスパート(約 55.4GiB)が、BIOS で割り当てた 96GB の VRAM に載りました。起動は約 29 秒、読み込み後の VRAM の空きは約 27.7GiB(256K・KV キャッシュ int8・MTP あり・1 本)、システム RAM の使用は約 5.9GB でした。

前回の llama.cpp では、PLE(約 29GB の n-gram の表)を SSD に置く工夫をしましたが、今回はモデル全体が VRAM に収まっています。「BIOS で VRAM を大きく取る」配分だからこそ取れるやり方です。

実際の手順

実際の手順です(v0.1.40.2、Strata の公式ドキュメント docs/STRIX_HALO.md に沿ったもの)。ROCm は AMD の TheRock ビルド(7.14.1、Ryzen AI Max+ 395 向け)を自分のフォルダに展開して使います。root は要らず、システムに入っている ROCm には触れません。

# 1. ROCm(TheRock 7.14.1、Ryzen AI Max+ 395 (gfx1151) 向け)をユーザー領域に展開
mkdir -p ~/rocm && cd ~/rocm
curl -LO https://repo.amd.com/rocm/tarball-multi-arch/therock-dist-linux-gfx1151-7.14.1.tar.gz
mkdir install && tar -xzf therock-dist-linux-gfx1151-7.14.1.tar.gz -C install
export SDK=$HOME/rocm/install
export ROCM_PATH=$SDK HIP_PATH=$SDK HIP_PLATFORM=amd
export PATH=$SDK/bin:$SDK/lib/llvm/bin:$PATH
export LD_LIBRARY_PATH=$SDK/lib:$SDK/lib/rocm_sysdeps/lib:$SDK/lib/llvm/lib:${LD_LIBRARY_PATH:-}

# 2. Strata をビルド(公式手順どおり。EVO-X2 では約 4 分)
git clone https://github.com/Niko1221/Strata.git && cd Strata && git checkout v0.1.40.2
cmake -S . -B build-halo -G Ninja -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_HIP_ARCHITECTURES=gfx1151 \
  -DCMAKE_HIP_COMPILER=$SDK/lib/llvm/bin/clang++ -DCMAKE_HIP_COMPILER_ROCM_ROOT=$SDK \
  "-DCMAKE_PREFIX_PATH=$SDK;$SDK/lib/rocm_sysdeps;$SDK/lib/llvm" \
  "-DCMAKE_HIP_FLAGS=--rocm-path=$SDK --rocm-device-lib-path=$SDK/lib/llvm/amdgcn/bitcode"
cmake --build build-halo --target strata -j 8

# 3. GGUF(unsloth UD-IQ4_XS)を Strata の形式に変換(約 30 秒)
.venv/bin/python tools/iq_pack.py \
  --gguf <モデル置き場>/Qwen3.8-Flash-Next-UD-IQ4_XS-00001-of-00003.gguf \
  --out packs/ud-iq4_xs --compat-bf16

--compat-bf16 は必須です。この GGUF が Q8_0 で持っている小さな射影を、Strata は BF16 で読むため、変換時に丸めが入ります(この丸めが、llama.cpp と出力が完全には一致しない理由です)。MTP のドラフトは、公式ドキュメント(docs/ORCA.md の準備の節)のとおりに作って mtp/rt に置きます。

サーバの設定は strata-ud-iq4_xs.json のような JSON に書きます。EVO-X2 で使ったものは次のとおりです。

{
  "exe": "build-halo/strata",
  "args": [
    "--pack", "packs/ud-iq4_xs",
    "--native", "<モデル置き場>/Qwen3.8-Flash-Next-UD-IQ4_XS-00001-of-00003.gguf",
    "--expert-profile", "data/expert-profile.bin",
    "--expert-cache", "24576", "--mmap-experts",
    "--prefill", "16384", "--max-context", "262144", "--kv", "int8",
    "--spec", "4", "--spec-min-p", "0.5",
    "--mtp", "mtp/rt", "--lookup-chain", "3", "--mtp-q4", "all"
  ],
  "cwd": ".",
  "tokenizer": "packs/ud-iq4_xs/tokenizer",
  "model_name": "qwen3.8-flash-next-ud-iq4_xs",
  "log": "strata-ud-iq4_xs.log",
  "fit_max_tokens": true
}
  • --expert-cache 24576 --mmap-experts が、上で書いた EVO-X2 向けの指定です(公式の例は "--expert-cache", "auto")
  • --prefill 16384 にしているのは、後述の hipBLASLt の調整表がこの大きさのプロンプトまで含んでいるためです
  • 2 本同時に処理するときは "parallel": 2 を足します(1 本あたり VRAM を約 3.65GiB 多く使い、読み込み後の空きは約 20.2GiB でした)

起動のときは、公式ドキュメントの「速い構成」の環境変数と、hipBLASLt の調整表を渡します。調整表は、対応したカードなら setup が渡してくれますが、Ryzen AI Max+ 395 では自分で指定します(指定しないと、プロンプトの読み込みが遅くなります)。

export STRATA_HIPBLASLT_TUNING=$PWD/tools/hip/gfx1151-hipblaslt-100401.txt
export STRATA_PF_FUSED=1 STRATA_PF_GEMM=1 STRATA_HC_UPMIX=1 STRATA_PA_FAST=1
export STRATA_HIP_WMMA=1 STRATA_SELECT_WMMA=1 STRATA_HC_Q8=1
export STRATA_PF_SWITCH_MIN_T=4096

.venv/bin/python -m serve.server --engine strata --config strata-ud-iq4_xs.json --host 0.0.0.0 --port 8095

起動ログに prefill gemm: hipBLASLt tuning enabled (… gfx1151, version 100401) と出れば、調整表が効いています。環境変数の 7 つは、既定より速い代わりに丸め方が変わるもので、公式は KL(出力分布の差)を測ったうえで「速い構成」として案内しています。Ryzen AI Max+ 395 向けの既定の 18 個のスイッチは、エンジンが自動で有効にします。

動かすときのコツ 2:OpenCode と組み合わせるなら "fit_max_tokens": true

Strata は、「プロンプト+max_tokens」がコンテクスト長を超えるリクエストを HTTP 400 で断ります。OpenCode(V1)は毎回 max_tokens として約 32,000 を送るので、会話が約 23 万トークンに達したところで、compaction が始まる前に止まってしまいました。

Strata の設定に "fit_max_tokens": true(残りの余地に合わせて max_tokens を縮める)を入れると解消しました。

256K の安定性

5 つの試験(合計 約 6.8 時間)を行いました。速度などの測定も含めると、約 10.6 時間動かし続けています。どの試験も、前回リセットが起きた 8.8 万〜10.4 万トークンの帯を通り越して、20 万トークン前後まで到達しています。

図 1 各試験で到達したコンテクスト

試験 やり方 時間 最大コンテクスト 結果
API で会話を育てる 毎ターン資料を足し、思考あり(high)で長い回答を生成 55 分(31 ターン、生成 約 13.9 万トークン) 約 23.1 万(最終 23.7 万) 異常なし。前回リセットした 8.8 万〜10.4 万トークンを、GPU 使用率 99〜100% で生成しながら約 32 分かけて通過
OpenCode V1 で実使用 同じセッションに依頼を重ねる(調査、レビュー、編集、要約) 約 1.5 時間 約 23.5 万(compaction で 9.2 万へ) 異常なし
OpenCode V2 で実使用 同じ依頼 84 分 約 19 万(compaction 3 回) 異常なし
2 本同時(parallel 2、V1 と V2) 別々のセッションを同時に 約 97 分 各 約 18 万 異常なし
2 本同時(parallel 2、API で最大まで) 会話を 2 本同時に育てる 82 分 21.7 万と 23.2 万を同時に保持 異常なし。毎ターン全文を読み直す厳しい条件で、21.4 万トークンの読み込みに 7.6 分かかる場面もあった
  • 通算: 経過 約 10.6 時間のうち、GPU 使用率 95% 以上が約 8.2 時間。リセット 0 回、サーバの停止 0 回
  • 監視: 1 秒ごとに GPU の状態・温度・電力・メモリを記録し、別の PC にも同時に送りました(前回、リセットで記録ごと消えた反省から)。記録の欠けはありませんでした
  • 温度と電力: GPU 温度は最大 94℃、電力は最大 約 117W

コンテクストが長くなっても、出力速度は大きく落ちませんでした(API で会話を育てる試験、思考あり、MTP あり)。10 万トークンを超えたところで約 50 tok/s から約 43 tok/s に下がりますが、その先は 40 tok/s 台を保っています。

図 4 コンテクスト長と出力速度

コンテクスト 出力速度(平均)
5 万未満 約 50 tok/s
5〜10 万 約 52 tok/s
10〜15 万 約 43 tok/s
15〜20 万 約 42 tok/s
20 万以上 約 43 tok/s

2 本同時は、OpenCode を 2 つ並べて使う(たとえば調査用と実装用)個人利用を想定したものです。Strata の設定で "parallel": 2 にして測りました。1 本あたりの出力速度は、1 本だけのときの 45〜50 tok/s から 15〜21 tok/s に下がり、合計は 1 本のときとほぼ同じでした。2 本同時に使うと速くなるわけではなく、待たずに済むようになる、という使い方です。

OpenCode V1 と V2

項目 V1(1.18.35) V2(2.0.24)
256K での実使用 ○(最大 約 23.5 万) ○(最大 約 19 万、compaction 3 回)
ツールの呼び出し read / grep / glob / edit / write / bash が動作 read / grep / glob / edit / write / shell / execute が動作。形式の崩れなし
設定ファイル opencode.json opencode.jsonc(キーの名前や構造が V1 と別物)
  • compaction は時間がかかる。 要約のリクエストは通常と先頭が違うため、コンテクスト全体を初めから読み直します。23.5 万トークンで 221 秒、15.8 万トークンで約 2 分かかり、その間エージェントは無音になります。OpenCode のタイムアウトは 900 秒にしました
  • ふだんはキャッシュがよく効く。 実使用では、入力の 92〜96% がキャッシュから読まれていました(2 本同時でも効いていました)
  • V2 はモデルを固定しておくこと。 V2 は -m でモデルを指定しないと、外部の既定のモデルを選びます。ローカルの LLM だけで使うなら、設定ファイルでモデルを固定するか、-m を必ず付けてください

実際の開発に使ってみて

この構成は、その後ラボの実際の開発の推論先として使っています(Strata はその間に版を上げています)。たとえば、自分のデータを整理するエージェントの開発です。ブラウザを人と同じ速さで操作して、自分のデータ(画像とその情報)を集め、一覧で見られる Web 画面まで、OpenCode に作らせました。

データを外に出さずに、調査・操作・コーディングまでをローカルの LLM で回せる。外に出せないデータを扱う開発で、これが現実的な選択肢になってきたと感じています。

速度

1 件ずつ、思考なしで測りました。MTP の有無で 2 本に分けているのは、前回の llama.cpp と DGX Spark が MTP なしで測ったものだからです。

図 2 出力速度

構成 出力速度(3 回の中央値)
EVO-X2 + Strata(MTP あり) 43.6 tok/s
EVO-X2 + Strata(MTP なし) 28.5 tok/s
前回:EVO-X2 + llama.cpp(Vulkan、MTP なし) 20.4 tok/s
参考:DGX Spark + SGLang(NVFP4、MTP なし) 27.0 tok/s

MTP なしどうしで比べても、Strata は llama.cpp の約 1.4 倍でした。

長いプロンプトを初めて読み込む(キャッシュなし)時間です。エージェントとして使うときは、資料やコードをまとめて読ませる場面が多いので、ここが速いかどうかが体感に効きます。

図 3 長いプロンプトの初回読み込み時間

長さ Strata(MTP あり) Strata(MTP なし) 前回:llama.cpp 参考:DGX Spark
約 2,500 トークン 3.1 秒 3.1 秒 10.5 秒 2.9 秒
約 22,800 トークン 19.9 秒 19.7 秒 約 65 秒(推定) 14.3 秒
約 63,300 トークン 53.1 秒 53.5 秒 約 218 秒(推定) 40.6 秒
  • Strata の読み込みは、llama.cpp の約 3〜4.5 倍の速さで、DGX Spark の 8 割弱でした
  • 同じプロンプトの 2 回目(キャッシュあり)は 0.05〜0.36 秒です
  • llama.cpp の約 22,800 と約 63,300 トークンの値は、一部キャッシュが効いていた実測値をキャッシュなしに換算した推定値です(前回の記事と同じ値)

日本語の品質

構成 JamC-QA(300 問)
Strata(MTP あり) 66.0%
Strata(MTP なし) 66.0%
前回:llama.cpp(Vulkan) 66.67%

300 問で 2 問の差です。Strata の形式に変換するときの丸め(後述)などの範囲とみています。

前回のリセットについて

「エンジンを替えたらリセットしなくなった」のは事実ですが、原因は分かっていません。前回のリセットの記録を読み直したので、分かったことを書いておきます。

記録から分かったこと

  • 前回、予期しない停止は 2 回ありました。どちらも llama.cpp(Vulkan)が、約 10.4 万トークンと約 8.85 万トークンのコンテクストで生成している最中でした
  • 2 回とも、GPU のエラー(計算キューのタイムアウト、Device lost、GPU のリセット、ページフォルトなど)はカーネルのログに残っていませんでした
  • 2 回目は 46 秒後に自分で再起動し、次の起動のカーネルのログに、前回のリセット理由として「internal CPU shutdown event occurred」と記録されていました

最後の 1 行は、Linux 6.16 から入った機能です。AMD の CPU が持っている「前回のリセット理由」のレジスタを、起動時に読んで表示してくれます。

x86/amd: Previous system reset reason [0x00800800]: internal CPU shutdown event occurred

つまり、GPU のエラーではなく、CPU 側の事象としてシステム全体がリセットされたことになります。

「Vulkan だから落ちた」とは言えない理由

llama.cpp の Vulkan で、長いコンテクストのときに GPU の計算キューがタイムアウトする、という報告は複数あります(#21724、discussion #27154)。最初はこれを疑いました。ただし、これらの報告の多くはプロセスの異常終了で済んでいて、今回のようなシステム全体のリセットとは症状が違います。GPU のエラーも記録されていませんでした。

また、次の点からも「Strata だから直った」とは言えません。

  • 電力は Strata のほうが高い。 前回のリセットの直前は約 80W、Strata の試験では最大 約 117W でした。「負荷が軽いから落ちなかった」という説明は成り立ちません
  • カーネルも変わっている。 前回のリセットは 7.0.0-34 のときで、今回の試験は 7.0.0-38 です
  • 回数が少ない。 偶然を否定できるほどの回数ではありません

Ryzen AI Max+ 395 では、似た報告が多い

Ryzen AI Max+ 395 を積んだ機械では、高負荷の推論中にシステムごと落ちる、という報告がいくつもの機種から出ています。記録される理由は報告ごとに違い、「ACPI の電源状態の遷移」や「訂正できないエラーによるデータファブリックの sync flood」などがあります(ROG Flow Z13 の報告、Beelink GTR9 Pro の報告、GPU と NPU を同時に使ったときの報告)。機種、ファームウェア、負荷のかけ方によって出たり出なかったりするようです。

同じ症状に当たった人は、次の起動でカーネルのログの「Previous system reset reason」を見てください。

journalctl -k -b | grep "Previous system reset reason"

GPU 側の問題か、本体側の問題かを切り分ける手がかりになります。

測定の条件と注意

  • MTP の扱いが構成で違う。 前回の llama.cpp と DGX Spark は MTP なしです。公平に比べるなら、Strata の MTP なし(28.5 tok/s)を使ってください
  • Strata の「MTP なし」は、投機デコードを完全には切っていない。 今回の形式のモデルでは最低限の投機デコードが必須で、簡易なドラフト(受理率 約 49%)だけが残る構成です
  • モデルの変換。 Strata の形式に変換するとき、一部の値を BF16 に丸めています(公式の注記あり)。そのため llama.cpp と出力が完全には一致しません
  • 思考の止め方。 前回は llama.cpp の --reasoning off、今回はリクエストの reasoning_effort: none です
  • 速度の測り方。 前回と同じベンチマークのクライアント(ShareGPT の 200 プロンプト)を使いましたが、Strata に対してはクライアント側の一部の値が正しく出ませんでした(TTFT が数ミリ秒になる、MTP なしで出力を少なく数えるなど)。そのため、出力速度は Strata のサーバのログから計算しました
  • 回数。 出力速度は 3 回の中央値、長いプロンプトは各 1 回です
  • 版。 数字はすべて v0.1.40.2 での測定です。Strata はその後も版を上げていて、本記事の公開時点では 0.2 系が出ています

未解決の点

  1. 一晩以上の連続運転は、この版ではしていない。 1 回の連続運転は最長 約 97 分、通算の高負荷は約 8.2 時間です。その後の 0.2.4.1 では、OpenCode V2 で 6 時間を超える連続運転をして異常がないことを確かめました。これは次の記事で書きます
  2. 出力が 1 回だけ壊れた。 OpenCode V1 で約 16.4 万トークンのとき、最後の応答が壊れた短い文で止まりました。約 780 ステップ中この 1 回だけで、原因(モデル、量子化、エンジン、MTP)は切り分けていません
  3. GPU 温度が最大 94℃。 長時間の高負荷では冷却に注意が必要です

まとめ

前回「残念!」で終わった EVO-X2 の 256K コンテクストは、Strata で動きました。速度も上がり、OpenCode と組み合わせて実際のエージェントとして使えています。

一方で、前回のリセットの原因はまだ分かっていません。Ryzen AI Max+ 395 で長時間の高負荷をかける人は、監視の記録を別の機械にも送り、リセットしたら「Previous system reset reason」を確かめることをおすすめします。

英語版のリポジトリ(起動の設定、監視・測定のスクリプト、生データ): https://github.com/nabe2030/strata-evo-x2-256k

Strata への報告: #4032(Linux の Ryzen AI Max+ 395 での実測)、#4033(VRAM を大きく取った構成で --expert-cache auto が落ちる件)、#4034(ドキュメントの提案)

おわりに — 当ラボについて

筆者は NPO法人 IoTメディアラボラトリーで、IoT 研究とあわせて AI 分野の検証を担当しています。東京大学・本郷キャンパス 大学院工学系研究科の同名のラボで行っていた IoT 研究が独立し、研究機関として活動を続けている組織です。
私がやっていることは、本記事のようなローカル LLM の実機検証が中心です。新しいモデルが出るたびに手元のハードで動かし、速度・日本語知識・コーディング・マルチモーダルの 4 軸で測り、動かなければ原因を突き止めるところまでやります。ベンダーの公称値ではなく、実際に自分の機械で何が起きるかを知りたいからです。
そのぶん、計算資源はいくらあっても足りません。もっと GPU が欲しい(笑)。機材の提供、検証のご依頼、共同研究など、お声がけいただけると喜びます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?