AMD Ryzen AI MAX+ 395の内蔵GPU、Radeon 8060Sで、NVIDIA Nemotron 3.5 Super VL 120B-A12BのGGUFを動かしました。96 GBの共有メモリ環境で、テキスト生成、PNG/JPEGの認識、複数画像による時系列理解、MP4入力を検証しています。
テキスト生成は約19.2 tokens/s、短文の初回応答時間は約0.52秒でした。画像では図形・色・文字を認識でき、4秒の合成動画では移動方向や物体の出現を回答できました。ただし、動画の出現時刻を1秒早く答える誤認識もありました。
この記事には、2026年10月18日の実行条件、再現用コマンド、認識結果、メモリ使用量を記載します。Qwen3.6の2モデル、Nemotron 3.5 Boltとの同一条件での速度比較も行いました。
検証環境とモデル
NVIDIAの公式BF16モデルを基にした、AtomicChat配布のGGUFを使用しました。言語モデル本体はAD-IQ3_XXS、画像用のエンコーダーとprojectorはF16版です。
| 項目 | 構成 |
|---|---|
| CPU | AMD Ryzen AI MAX+ 395 |
| GPU | Radeon 8060S、gfx1151 |
| 共有メモリ | 96 GB構成、OSのMemTotalは約90.7 GiB |
| OS | Ubuntu 26.04.1 LTS |
| ROCm環境 |
/opt/rocm/core-10.1配下のHIPコンパイラーを使用 |
| コンパイラー表示 | HIP 7.16.26385、AMD clang 24.0.0git |
| llama.cpp | build 11716、コミット797de63b2fa7396dcc8caca76834c699ac84e1c3
|
| 言語モデル | Nemotron 3.5 Super VL 120B-A12B、AD-IQ3_XXS |
| mmproj | mmproj-NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-F16.gguf |
ROCmの配置ディレクトリ名とhipcc --versionの表示は上表のとおりです。この構成での動作確認であり、別のROCmバージョンやOSまで検証したものではありません。容量は、GBを10進、GiBを2進として区別しています。
Super VLへの対応は、llama.cppのPR #30520で2026年10月15日にマージされています。対応コミットはcd0a5b6a180dff0048e5fd993098b21c0b2c91b8で、今回のビルドにはこの変更が含まれます。GGUFメタデータでは、言語モデルがnemotron_h_moe、画像projectorがnemotron_omniとなっていました。
GGUFとmmprojの取得
取得するファイルは次の3つです。分割GGUFは2つとも必要ですが、起動時に指定するのは1つ目です。
| ファイル | 容量 |
|---|---|
NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-AD-IQ3_XXS-00001-of-00002.gguf |
約44.57 GB |
NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-AD-IQ3_XXS-00002-of-00002.gguf |
約20.76 GB |
mmproj-NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-F16.gguf |
約1.73 GB |
| 合計 | 約67.06 GB |
以下のコマンド例では、説明用の作業ディレクトリを新しく作成し、モデルをmodelsに配置します。ROCm、CMake、Git、Hugging Face CLIのhf、FFmpeg/FFprobeは導入済みを前提とします。
mkdir supervl-demo
cd supervl-demo
hf download \
AtomicChat/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-GGUF \
--revision 119686c3e0821b5234c7f3d557b5d40dc1341a9d \
--include '*-AD-IQ3_XXS-*.gguf' \
'mmproj-NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-F16.gguf' \
--local-dir models
実験では取得後に3ファイルのSHA-256を配布元のメタデータと照合し、一致を確認しました。約67 GBはファイルの合計容量で、実行時には別途KVキャッシュ、画像処理用バッファ、ランタイムなどのメモリが必要です。
llama.cppをHIPでビルドする
既存の推論環境を変更せず、専用のソースとビルドディレクトリを用意しました。llama.cppのソースコードには変更を加えていません。
git clone https://github.com/ggml-org/llama.cpp.git
git -C llama.cpp checkout --detach 797de63b2fa7396dcc8caca76834c699ac84e1c3
export ROCM_PATH=/opt/rocm/core-10.1
export HIP_PATH="$ROCM_PATH"
export PATH="$ROCM_PATH/bin:$ROCM_PATH/lib/llvm/bin:$PATH"
cmake -S llama.cpp -B build-hip \
-DCMAKE_BUILD_TYPE=Release \
-DGGML_HIP=ON \
-DAMDGPU_TARGETS=gfx1151 \
-DCMAKE_HIP_ARCHITECTURES=gfx1151 \
-DGGML_HIP_NO_VMM=ON \
-DMTMD_VIDEO=ON \
-DLLAMA_SUBPROCESS=ON \
-DLLAMA_BUILD_TESTS=OFF
cmake --build build-hip -j 12 --target llama-mtmd-cli llama-server
build-hip/bin/llama-server --list-devices
build-hip/bin/llama-mtmd-cli --help
MTMD_VIDEOとLLAMA_SUBPROCESSは、FFmpegを起動する動画入力経路のために有効にしています。今回のGPUターゲットはgfx1151です。別のGPUでは、そのデバイスに対応するターゲットを指定する必要があります。
以降の起動例では、ファイル名を短く扱うために変数を定義します。
MODEL=models/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-AD-IQ3_XXS-00001-of-00002.gguf
MMPROJ=models/mmproj-NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-F16.gguf
画像・動画用サーバーの起動
まず小さな入力で確認するため、コンテキストを8192、画像を1枚256トークン、動画を1fpsに設定しました。
build-hip/bin/llama-server \
-m "$MODEL" --mmproj "$MMPROJ" \
-ngl 999 -c 8192 -np 1 \
-b 512 -ub 512 -t 16 \
--image-min-tokens 256 --image-max-tokens 256 \
--video-fps 1 --video-timestamp-interval 1000 \
--jinja --reasoning off \
--host 127.0.0.1 --port 18081 \
--metrics -lv 4
起動ログのうち、GPU配置に関係する部分を抜粋します。時刻などの接頭辞は省略しました。
load_tensors: offloaded 90/90 layers to GPU
load_tensors: ROCm0 model buffer size = 59742.52 MiB
load_tensors: ROCm_Host model buffer size = 544.00 MiB
llama_kv_cache: ROCm0 KV buffer size = 64.00 MiB
llama_memory_recurrent: ROCm0 RS buffer size = 164.69 MiB
clip_ctx: CLIP using ROCm0 backend
load_hparams: projector: nemotron_omni
言語モデルは90/90層がGPUに配置され、画像エンコーダーにもROCm0が使われました。ホスト側バッファや画像前処理もあるため、これを「すべての処理がGPUだけで実行された」とは解釈していません。
MTP用のblk.88テンソルが未使用という警告も出ました。今回の推論では投機的デコーディングを有効にしていません。
静止画の色・図形・文字を認識する
認識結果を確認しやすいよう、白背景に3つの図形と文字を置いた512×512画像を使いました。PNGとJPEGは同じ内容です。
| 対象 | 正解 |
|---|---|
| 左上 | 赤い円 |
| 右上 | 青い四角 |
| 下中央 | 緑の三角 |
| 上部の文字 | VISION TEST 42 |
同じ配置の画像を作るコードは以下です。Pillowを使用します。
from PIL import Image, ImageDraw, ImageFont
image = Image.new("RGB", (512, 512), "white")
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 30
)
draw.text((55, 20), "VISION TEST 42", fill="black", font=font)
draw.ellipse((60, 130, 180, 250), fill="#e32636")
draw.rectangle((290, 130, 410, 250), fill="#205de0")
draw.polygon([(256, 310), (180, 440), (332, 440)], fill="#129c48")
image.save("shapes.png")
image.save("shapes.jpg", quality=95)
APIでは画像をBase64で送信しました。Python標準ライブラリでリクエストする最小例を示します。これは応答を一括で受け取る例で、TTFTの計測コードとは別です。
import base64
import json
import urllib.request
with open("shapes.png", "rb") as f:
encoded = base64.b64encode(f.read()).decode()
content = [
{"type": "image_url", "image_url": {
"url": "data:image/png;base64," + encoded
}},
{"type": "text", "text": (
"List the three colored shapes and their positions. "
"Then transcribe the text exactly. Answer briefly."
)},
]
payload = {
"messages": [{"role": "user", "content": content}],
"temperature": 0, "seed": 42, "max_tokens": 160,
"cache_prompt": False,
"chat_template_kwargs": {"enable_thinking": False},
}
request = urllib.request.Request(
"http://127.0.0.1:18081/v1/chat/completions",
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(request, timeout=600) as response:
result = json.load(response)
print(result["choices"][0]["message"]["content"])
PNG、JPEGともに次の回答を得ました。
Red circle: top left. Blue square: top right. Green triangle: bottom center.
VISION TEST 42
図形・色・配置・文字はいずれも正解で、2回の検証でも同じ回答になりました。以下は2回目の計測値です。TTFTはリクエスト送信から最初の本文まで、全応答時間は送信から応答終了までを測っています。モデルロード時間は含めません。
| 入力 | TTFT | 全応答時間 | 生成速度 |
|---|---|---|---|
| PNG | 1.44秒 | 2.69秒 | 19.18 tokens/s |
| JPEG | 1.53秒 | 2.81秒 | 18.73 tokens/s |
この結果は、合成画像による基本的な認識確認です。自然画像や複雑なOCRの精度を示す評価ではありません。
CLIでも次の形式で画像を渡せます。今回も実行し、文字と3つの図形の正答、終了コード0を確認しました。CLIはモデル本来のthinking設定を使ったため、上表のreasoning offのAPI測定とは速度を比較していません。
build-hip/bin/llama-mtmd-cli \
-m "$MODEL" --mmproj "$MMPROJ" \
-ngl 999 -c 8192 -b 512 -ub 512 -t 16 -n 256 \
--image-min-tokens 256 --image-max-tokens 256 \
--jinja --image shapes.png \
-p 'List the colored shapes and read the text. Answer briefly.'
4秒の動画で移動方向と出現時刻を確認する
動画用には、512×512、8fps、4秒の合成MP4を用意しました。赤い円が左から右へ水平移動し、青い四角が2秒に初めて現れます。正解が決まっている素材を使い、入力順序と時刻に対応した回答が得られるかを確認しました。
検証動画を生成する短いコード例
上の静止画生成コードと同じPillowのフォントを使い、PNG列をFFmpegでMP4に変換します。
from pathlib import Path
import subprocess
from PIL import Image, ImageDraw, ImageFont
frames = Path("source-frames")
frames.mkdir(exist_ok=True)
font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 30
)
for i in range(32):
image = Image.new("RGB", (512, 512), "white")
draw = ImageDraw.Draw(image)
draw.text((65, 25), "MOTION TEST", fill="black", font=font)
x = 80 + round(352 * i / 31)
draw.ellipse((x - 36, 210, x + 36, 282), fill="#e32636")
if i >= 16:
draw.rectangle((370, 350, 450, 430), fill="#205de0")
image.save(frames / f"{i:03d}.png")
subprocess.run([
"ffmpeg", "-y", "-v", "error", "-framerate", "8",
"-i", "source-frames/%03d.png", "-c:v", "libx264",
"-pix_fmt", "yuv420p", "-movflags", "+faststart", "motion.mp4",
], check=True)
OpenCVで抽出した4画像をまとめて渡す
最初にOpenCVで0、1、2、3秒の4フレームを抽出しました。処理の要点は次のとおりです。
import cv2
cap = cv2.VideoCapture("motion.mp4")
fps = cap.get(cv2.CAP_PROP_FPS)
if not cap.isOpened() or fps <= 0:
raise RuntimeError("動画を開けないか、FPSを取得できません")
index, next_sample = 0, 0.0
try:
while next_sample < 4:
ok, frame = cap.read()
if not ok:
break
timestamp = index / fps
if timestamp + 1e-9 >= next_sample:
cv2.imwrite(f"frame-{next_sample:.0f}s.jpg", frame)
next_sample += 1.0
index += 1
finally:
cap.release()
APIのcontentには、「Frame 1, timestamp 0.0 seconds:」というテキスト、0秒の画像、次の時刻テキスト、次の画像、という順序で4枚を格納しました。各画像を別々に説明させて文章だけを要約する方式ではなく、4枚を1回の推論に渡しています。
質問は次のとおりです。
These frames are in chronological order. Which direction does the red circle move?
At what timestamp does the blue square first appear, or is it present from the first frame?
Answer briefly based only on the frames.
正順での回答は次のようになりました。
The red circle moves diagonally down and to the right.
The blue square first appears at timestamp 2.0 seconds.
右向きの移動と2秒の出現は合っていますが、実際には上下に動いていません。「斜め下」という余分な動きを回答しています。
次に、4枚の画像を逆順にし、時刻を0秒から振り直して同じ質問をしました。
The red circle moves to the left.
The blue square is present from the first frame.
入力順を反転すると、移動方向が左向きに変わり、青い四角も最初から存在すると回答しました。少なくとも今回の単純な例では、画像列の順序に応じて回答が変わっています。
MP4をAPIに渡す
llama.cppにはFFmpegで動画をフレーム化する実装があり、サーバーAPIのinput_videoを使えます。MP4を入力できますが、モデルが動画コンテナを直接解釈するわけではなく、内部で画像列に変換されます。
前述の画像APIの例では、contentを次のように置き換えればMP4を渡せます。payloadの構造や送信先は同じです。
with open("motion.mp4", "rb") as f:
encoded = base64.b64encode(f.read()).decode()
content = [
{"type": "input_video", "input_video": {"data": encoded}},
{"type": "text", "text": (
"Describe the motion of the red circle. "
"At what time does the blue square first appear? "
"Answer briefly using the timestamps."
)},
]
通常の質問では、2回とも次の回答になりました。
The red circle moves from left to right.
The blue square first appears at 1.00s.
移動方向は正解ですが、出現時刻を1秒早く答えています。今回使用した動画入力の実装を確認すると、タイムスタンプのテキストは各フレーム画像の後に挿入されます。そこで、追加検証では質問を次のように変更しました。
For each of the four sampled video frames, list the frame number in order,
its timestamp, the red circle position (left, center-left, center-right, right),
and whether a blue square is visible.
Read each timestamp as the time of the image immediately before it.
Then state when the blue square first appears.
この質問では、以下の対応を正しく回答しました。
| フレーム | 回答時刻 | 赤い円の位置 | 青い四角 |
|---|---|---|---|
| 1 | 00:00 | 左 | なし |
| 2 | 00:01 | 中央左 | なし |
| 3 | 00:02 | 中央右 | あり |
| 4 | 00:03 | 右 | あり |
タイムスタンプと画像の対応を明示した質問では改善しましたが、質問の詳しさも変えているため、挿入位置だけが誤答の原因だとは断定できません。動画内の時刻を扱う用途では、正解データとの照合が必要です。
動画入力の応答時間
| 入力 | TTFT | 全応答時間 | 生成速度 |
|---|---|---|---|
| 正順4フレーム | 4.78秒 | 6.11秒 | 18.76 tokens/s |
| 逆順4フレーム | 4.79秒 | 5.76秒 | 18.52 tokens/s |
| MP4、通常質問 | 4.91秒 | 6.14秒 | 17.89 tokens/s |
| MP4、各フレームの時刻を明示した質問 | 4.76秒 | 10.12秒 | 19.03 tokens/s |
これは1回目の確認に続けて行った2回目の計測値で、3回平均や中央値ではありません。最後の質問は103トークンを生成しており、通常質問の23トークンより回答が長いため、全応答時間も増えています。
動画は4秒、512×512、1fps抽出という小さな条件です。長時間・高解像度の動画や、人物の行動認識は今回評価していません。
画像・動画推論のメモリ使用量
画像・動画用サーバーでは、0.5秒ごとにRSS、MemAvailable、GTT、VRAM、GPU使用率を記録しました。主要な値を示します。
| 段階 | プロセスRSS最大 | GTT最大 | MemAvailable最小 |
|---|---|---|---|
| ロード済み待機 | 1.14 GiB | 60.67 GiB | 24.01 GiB |
| PNG処理 | 1.55 GiB | 60.83 GiB | 23.58 GiB |
| JPEG処理 | 2.06 GiB | 60.83 GiB | 22.94 GiB |
| 正順4画像 | 2.57 GiB | 60.83 GiB | 22.49 GiB |
| 逆順4画像 | 3.09 GiB | 60.83 GiB | 21.85 GiB |
| MP4、通常質問 | 3.58 GiB | 60.83 GiB | 21.66 GiB |
| MP4、詳細質問 | 3.58 GiB | 60.83 GiB | 21.59 GiB |
GTTとVRAMはシステム全体のGPUメモリカウンターで、ほかのプロセスの分も含みます。APUの共有メモリ上の割り当てを含むため、RSS・GTT・VRAMを単純に足して総使用量にすることはできません。RSSが数GiBだから数GiBで動く、という解釈もできません。
開始時のMemAvailableは約85.94 GiB、測定中の最低値は約21.59 GiBで、差は約64.35 GiBでした。この差もモデル以外の活動に影響されますが、96 GB構成で今回の処理を実行できた際のメモリ余裕の目安になります。
後半ほどRSSが増えているのは、同じサーバーでリクエストを順次処理した際の値です。サーバーは再帰状態のチェックポイントも保持するため、各入力を単独で起動した場合の必要量とは一致しません。長時間の反復処理でメモリ使用量が収束するかは未検証です。
GPU使用率の観測最大は99%で、2回のAPI検証にOOM、ROCmエラー、異常終了はありませんでした。HTTP受付可能になるまでは25.05秒と32.13秒でしたが、ディスクキャッシュの状態を揃えたコールドロード比較ではありません。
テキストLLMとしてQwen3.6・Boltと比較する
Super VLに画像を与えず、テキストLLMとしても比較しました。画像用サーバーを停止してから、4モデルを同じllama-serverで1つずつ起動しています。テキスト測定ではmmprojをロードしていません。
比較条件
| 項目 | 設定 |
|---|---|
| llama.cpp、ROCm | 全モデルで同じビルド・実行環境 |
| GPU配置 | 全層オフロードをログで確認 |
| コンテキスト | 8192 |
| 同時スロット | 1 |
| バッチ/マイクロバッチ | 512/512 |
| CPUスレッド | 通常・入力処理とも16 |
| Flash Attention | on |
| thinking | off |
| MTPを含む投機的デコーディング | 無効 |
| temperature/seed | 0/42 |
| 生成上限 | キャッシュなし128、キャッシュあり32トークン |
| 測定回数 | ウォームアップ後、各条件3回 |
共通の起動オプションは以下です。MODELを比較対象のGGUFに切り替え、モデルごとにサーバーを起動し直しました。
build-hip/bin/llama-server \
-m "$MODEL" -ngl 999 \
-c 8192 -np 1 -b 512 -ub 512 -t 16 -tb 16 \
-fa on -fit off --spec-type none \
--jinja --reasoning off --perf \
--host 127.0.0.1 --port 18082 -lv 4
比較したGGUF構成は次のとおりです。Dense/MoE、規模、量子化方式が異なるため、量子化条件を揃えたモデル系列単体の比較ではありません。
| モデル | 使用ファイル/量子化 | GPU配置 |
|---|---|---|
| Qwen3.6-35B-A3B | Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf |
41/41層 |
| Qwen3.6-27B |
Qwen3.6-27B-MTP-Q8_0.gguf、MTPは無効 |
66/66層 |
| Nemotron 3.5 Bolt 74B-A9B | NVIDIA-Nemotron-3.5-Bolt-74B-A9B-24GB.gguf |
89/89層 |
| Nemotron 3.5 Super VL 120B-A12B | AD-IQ3_XXS、2分割GGUF | 90/90層 |
入力とTTFTの測り方
短文は写真コレクションの整理とバックアップについて、600語以上のガイド作成を依頼する同一の英文です。長文では次の記録文を反復し、末尾にセンサーデータの保存・検証・バックアップのガイド作成を依頼しました。
The archive contains a numbered record of a routine sensor reading.
長文の反復数は、各モデルの/tokenizeで本文が約2048、約7168トークンになるよう二分探索で調整しています。そのため、モデル間で質問と反復文は共通ですが、長文全体の文字列は完全同一ではありません。チャットテンプレート込みの実入力数は次のとおりです。
| モデル群 | 短文 | 約2K | 約7K |
|---|---|---|---|
| Qwen3.6の2モデル | 56 | 2053 | 7177 |
| Bolt、Super VL | 62 | 2059 | 7183 |
TTFTは、localhostへHTTPリクエストを送信する直前から、SSEで最初の空でない本文を受け取るまでを測りました。roleだけのイベントは数えません。モデルロードと短いウォームアップは測定から除外しています。
計測コードの中心部分を示します。サーバーの自動起動・終了、入力長の調整、生イベントの保存、集計処理は省略しています。
import json
import time
import urllib.request
def measure(prompt, max_tokens=128, cache=False):
payload = {
"messages": [{"role": "user", "content": prompt}],
"temperature": 0, "seed": 42, "max_tokens": max_tokens,
"stream": True, "stream_options": {"include_usage": True},
"cache_prompt": cache, "timings_per_token": True,
"chat_template_kwargs": {"enable_thinking": False},
}
request = urllib.request.Request(
"http://127.0.0.1:18082/v1/chat/completions",
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"},
)
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
first, timings = None, None
start = time.perf_counter()
with opener.open(request, timeout=600) as response:
for line in response:
if not line.startswith(b"data: "):
continue
data = line[6:].strip()
if data == b"[DONE]":
break
event = json.loads(data)
for choice in event.get("choices", []):
if choice.get("delta", {}).get("content") and first is None:
first = time.perf_counter() - start
timings = event.get("timings") or timings
return first, timings["predicted_per_second"], timings.get("cache_n", 0)
生成速度はサーバーのtimings.predicted_per_secondを使います。キャッシュなしの全試行で、実際に128トークンを生成してlengthで終了し、cache_n=0であることを確認しました。
生成速度とキャッシュなしTTFT
次表は各3回の中央値です。生成速度の単位はtokens/s、TTFTの単位は秒です。
| モデル | 短文生成 | 短文TTFT | 約2K TTFT | 約7K TTFT | 約7K生成 |
|---|---|---|---|---|---|
| Qwen3.6-35B-A3B/UD-Q4_K_XL | 50.47 | 0.148 | 1.406 | 4.917 | 48.72 |
| Qwen3.6-27B/Q8_0 | 7.74 | 0.413 | 5.660 | 19.783 | 7.56 |
| Nemotron 3.5 Bolt/24GB版 | 30.59 | 0.311 | 3.683 | 12.405 | 30.28 |
| Nemotron 3.5 Super VL/AD-IQ3_XXS | 19.20 | 0.517 | 6.272 | 20.053 | 19.12 |
今回の構成では、Super VLの生成速度はBoltの約63%でした。約7Kの入力でも生成速度はほぼ維持していますが、最初の本文が出るまでには約20秒かかっています。短い質問への応答と、長い文書を毎回読み直す用途では待ち時間が異なります。
Qwen3.6-35B-A3Bは今回の4構成で最も高速でした。一方、Qwen3.6-27BのQ8_0版は約7.7 tokens/sです。規模の名前だけで速度を判断せず、Dense/MoEや量子化形式を含めて比較する必要があります。今回の測定だけで、速度差の要因を個別に切り分けたとはいえません。
約7K入力のばらつきは次のとおりです。
| モデル | TTFT 3回(秒) | 生成速度3回(tokens/s) |
|---|---|---|
| Qwen3.6-35B-A3B | 4.914、4.917、4.922 | 48.75、48.72、48.69 |
| Qwen3.6-27B | 19.761、19.785、19.783 | 7.56、7.56、7.56 |
| Bolt | 12.360、12.405、12.432 | 30.32、30.28、30.25 |
| Super VL | 20.036、20.060、20.053 | 19.12、19.15、19.12 |
同一長文をキャッシュした場合
同じ約7Kプロンプトを同じスロットで繰り返す条件も測りました。キャッシュを有効にしたリクエストで準備した後、生成上限32トークンで3回測定しています。
| モデル | キャッシュなしTTFT | キャッシュありTTFT | 実際の再利用トークン数 |
|---|---|---|---|
| Qwen3.6-35B-A3B | 4.917秒 | 0.064秒 | 7173 |
| Qwen3.6-27B | 19.783秒 | 0.197秒 | 7173 |
| Bolt | 12.405秒 | 0.097秒 | 7179 |
| Super VL | 20.053秒 | 0.133秒 | 7179 |
全モデルで3回とも上表のトークン数の再利用を確認しました。Super VLでも、同一長文の再利用ならTTFTは約0.13秒に短縮しています。
これは同じ入力を同じスロットで繰り返した場合です。新しい文書、内容が増えた会話、別のクライアント、キャッシュが失われた状態でも同じ値になるとは限りません。
計算・日本語抽出・論理問題の基本動作
速度測定とは別に、次の3問を各モデルに与えました。
| テスト | 問題の要点 | 期待したJSON |
|---|---|---|
| 計算 | 17×24 | {"answer":408} |
| 日本語抽出 | 「会議は2026年10月18日、東京で開催。参加者は12人。」から抽出 | {"date":"2026-10-18","city":"東京","participants":12} |
| 論理 | 琥珀色の箱はすべて重く、重い箱は棚Aにない。琥珀色の箱を棚Aに置けるか | {"possible":false} |
いずれもJSONだけを返すよう指示しました。全モデルで内容は正解でしたが、Qwen3.6-35B-A3Bの日本語抽出回答にはMarkdownコードフェンスが付いていました。
| モデル | 内容一致 | 応答全体がそのままJSONとして解析可能 |
|---|---|---|
| Qwen3.6-35B-A3B | 3/3 | 2/3 |
| Qwen3.6-27B | 3/3 | 3/3 |
| Bolt | 3/3 | 3/3 |
| Super VL | 3/3 | 3/3 |
「内容一致」はコードフェンスを除去して正解JSONと照合した結果です。3問だけの基本動作確認なので、推論能力や日本語能力全体の優劣を評価するものではありません。
テキスト推論時のメモリ
画像エンコーダーをロードしない比較測定中の値です。画像・動画用の測定とはリクエスト数や状態が異なります。
| モデル | プロセスRSSピーク | GTT最大 | MemAvailable最小 |
|---|---|---|---|
| Qwen3.6-35B-A3B | 1.96 GiB | 21.00 GiB | 63.15 GiB |
| Qwen3.6-27B | 3.87 GiB | 26.47 GiB | 55.70 GiB |
| Bolt | 3.67 GiB | 20.68 GiB | 61.40 GiB |
| Super VL | 3.69 GiB | 59.27 GiB | 23.07 GiB |
ここでもRSSとGTTを合算してはいけません。今回のSuper VLは画像用サーバーでもテキスト専用でも実行できましたが、同じ96 GB構成で任意の画像枚数やコンテキスト長まで収まるという保証ではありません。
今回確認できた範囲
Radeon 8060Sとllama.cppのHIPバックエンドで、Super VLのAD-IQ3_XXSを全層GPUオフロードし、画像エンコーダーもGPUで実行できました。テキスト生成は約19.2 tokens/sで、合成静止画の認識と、短い動画のフレーム列・MP4入力も動作しました。
一方、動画では存在しない斜め移動の付加と、出現時刻の誤認識がありました。時刻と画像の対応を明示すると正答した例はありますが、これだけで実動画の時刻精度を保証することはできません。
残る検証は、自然画像・実動画の品質、長時間入力、解像度やフレーム数を増やした際のメモリ、長期運転の安定性です。テキスト比較も反復した合成長文を使い、モデル順を固定した3回の逐次測定なので、異なる入力や並列負荷、電力状態で結果は変わります。過去の別ビルドでの測定値とは混ぜず、この記事の共通条件での結果として扱っています。