検証機が、2台から1台になった
これまでの gwaw.jp の実機検証は、Pixel 10 Pro(Android / Chrome)と iPad mini A17 Pro(iPadOS / Safari)の2台体制でした。GPUもブラウザも違う2台で同じコードを走らせ、挙動の差を記事にしてきました。
今回、その2台を手放して Motorola razr fold に乗り換えました。使うアプリは Android に集中している一方、iPad mini のサイズ感も捨てがたい。開けば8.1インチ、閉じれば6.6インチ、FeliCa も付いて普段使いにも困らない。2台をひとつにまとめる、という買い方です。
では、過去の記事で測ってきた数字は、この1台でどうなるのか。4本のベンチマークページを順番に開いて確かめました。
メイン 8.1インチ / アウト 6.6インチ
Android / Chrome
iPadOS / Safari
60Hz
Android / Chrome
120Hz
razr fold の値は今回の実測、iPad mini と Pixel 10 Pro の値は各記事の公開時点の実測です。計測日もブラウザのバージョンも違うので、厳密な同条件比較ではありません。桁と傾向を見るための比較としてお読みください。
「Androidでは体感が伴わない」は、もう言えない
最初に開いたのは ブラウザでLLMは動くか のライブデモです。この記事の結論は「同じモデルで生成速度が8倍違う。Android では体感が伴わない」でした。
maxStorageBufferBindingSize は 2048MB。Pixel 10 Pro の16倍、iPad mini の2倍です。ベクトル検索編で「87,000文書の壁」を生んだあの上限が、この端末では大きく広がっています。
| モデル | サイズ | razr fold | iPad mini | Pixel 10 Pro |
|---|---|---|---|---|
| Qwen2.5-0.5B | 262MB | 29.3 | 47 | — |
| Qwen3.5-0.8B | 420MB | 16.5 | 22.6 | 3.0 |
| Qwen2.5-1.5B | 787MB | 18.1 ※ | 21.8 | 2.6 |
| Qwen3-1.7B | 892MB | 17.1 | 20.8 | 17.5 |
| Qwen3.5-2B | 1.0GB | 14.7 | 生成でクラッシュ | — |
0.8B は Pixel 10 Pro の約5.5倍、iPad mini の約7割。1.5B は 18.1 tok/s で Pixel 10 Pro の約7倍です。1.7B は 17.1 tok/s で、体感の応答も良好でした。そして iPad mini では「ロード成功 → 最初の質問でクラッシュ」だった 2B が、14.7 tok/s で最後まで生成できています。
同じモデルなら iPad mini のほうが速い。けれど、動かせるモデルの大きさは razr fold のほうが上でした。「どちらが上か」は、軸によって答えが変わります。
1.5B は、前日まで動かなかった
過去記事で「品質良好・最も安定」と評価した Qwen2.5-1.5B は、最初の日、razr fold で唯一生成できないモデルでした。ここに至るまでに、エラーを2種類踏んでいます。
- ロードの失敗(ネットワーク)
乗り換え直後は、1.5B のダウンロード自体が完了しませんでした。Failed to execute 'add' on 'Cache': Cache.add() encountered a network errorWebLLM はモデルを多数のシャードに分けて Cache API へ順に保存します。1本でも途中で途切れると、このエラーになります。回線も同時に変更していたので疑いましたが、時間を空けて再試行するとロードは成功しました。原因は特定できていません。 - 生成の失敗(GPU)
ロード成功後、最初の質問を投げた時点で次のエラーが出ます。Failed to execute 'mapAsync' on 'GPUBuffer': Buffer was unmapped before mapping was resolved.GPUからの結果読み戻しを待っている最中に、そのバッファが破棄されたときのエラーです。
切り分け:消去法は、モデル固有を指していた
| 試したこと | 結果 | 消えた仮説 |
|---|---|---|
| より小さい 0.5B / 0.8B を生成 | 成功 | 計測コード側の不具合 |
| より大きい 1.7B / 2B を生成 | 成功 | メモリ不足(サイズ依存) |
| 1.5B の q4f16_1 版を新規ダウンロードして生成 | 同じエラー | キャッシュ破損、f32 固有の問題 |
| 同じ Qwen2.5 系の 0.5B を生成 | 成功 | Qwen2.5 系統全体の問題 |
この時点で残ったのは「Qwen2.5-1.5B 用のモデルライブラリと、この端末のGPUドライバの相性」でした。
翌日、何事もなかったように動いた
原因を確定させるため、翌日にPCとのリモートデバッグ環境を整えて、もう一度 1.5B を試しました。結果は、エラーなし。ロード 72.7秒、decode 18.1 tok/s、33トークンを12.8秒で生成し、デモの判定も「生成まで成功。この端末で実用可能」でした。
前日の消去法は、ひとつ前提を見落としていました。すべての試行が「同じ日の、同じ端末の状態」で行われていたことです。モデルを入れ替えても、量子化を変えても、その前提は変わっていません。翌日になって変わったのは、端末とブラウザの状態のほうでした。
前日と違っていたのは、試す前に端末を再起動していたことです。モンテカルロのベンチでも、再起動の前後で WebGPU の値の荒れ方が大きく変わりました(§3)。再起動で GPU まわりの状態がリセットされたことが、最も有力な原因です。ただし、成功してしまったので、リモートデバッグで失敗時のログを取ることはできていません。確定ではなく、推定にとどまります。
「小さいモデルは動く、大きいモデルも動く、だからこのモデル固有」という推論は、失敗が再現することを前提にしています。その前提が崩れると、結論ごと崩れます。1日で2回失敗しても、別の日に試すまでは「このモデルは動かない」と書かない。実機検証の教訓として残しておきます。
原因が端末側の一時的な状態だったとしても、ユーザーの手元で同じことは起こりえます。生成エラー時に別モデルへ切り替える、あるいは再試行を促すフォールバックは、WebLLM でも持っておくべきです。
1.7B の「多言語で崩壊」は再現しなかった
過去記事では、Qwen3-1.7B は中国語やスペイン語が混ざった無意味な出力になり、「小型の reasoning モデルは量子化で暴走する」と結論していました。今回の razr fold では、同じ質問に自然で正確な日本語を返しています。
試したのは1回の出力だけなので断定はできません。ただ、あの崩壊がモデルの性質ではなく、端末側の数値的な問題だった可能性が出てきました。ここは質問を変えて再検証する価値があります。
100万点でも、GPU方式は上限に張り付く
次は ティックは何点まで描けるか の自動計測です。Canvas 2D・SVG・WebGL・WebGPU の4方式で、点数を1千から100万まで上げながら実効FPSを測ります。
| 方式 | razr fold | iPad mini (60Hz) | Pixel 10 Pro (120Hz) |
|---|---|---|---|
| Canvas 2D | 22 | 11 | 2 |
| SVG | 2 | 3 | 3 |
| WebGL | 90 | 49 | 121 |
| WebGPU | 91 | 60 | 119 |
Canvas 2D が伸びた
Canvas 2D は20万点まで91fpsを保ち、100万点でも22fps。iPad mini の2倍、Pixel 10 Pro の11倍です。元記事では Pixel について「描画時間は短いのにFPSが出ない」と書きましたが、razr fold ではその症状が出ていません。同じ Android の Chrome でも、合成・提示側の詰まり方は端末で違うようです。
91fps は性能の天井ではなく、OSの天井
GPU方式は全域で90〜91fpsに張り付きました。Pixel 10 Pro は120前後まで出ていたので、一見すると razr fold が劣って見えます。しかしこれは性能の限界ではありません。
メインディスプレイでもアウトディスプレイでも、上限は同じ90Hzでした。ディスプレイ設定には、ゲームのプレイ中はこの設定が上書きされ、120Hzが使用可能になる旨の説明があります。つまり通常アプリは90Hzまで、ゲームと認識されたアプリだけ120Hz、という振り分けで、Chrome は90Hz側に入っています。
同じ120Hz級のパネルでも、ブラウザに開放されるリフレッシュレートは機種ごとに違います。端末間でFPSを比べるなら、上限に対する到達率に直すか、描画時間(ms)で比べるほうが公平です。上限を割っている領域(Canvas 2D の50万点以上など)は、そのまま実力として比較できます。
元記事の「WebGL と WebGPU はデバイスで優劣が入れ替わる」という観察は、今回の条件では判定できませんでした。両者とも上限に当たっているためです。差を見るには、リングバッファの上限(現在105万点)を引き上げる必要があります。
WebGPU の逆転点が、10倍遠くなった
3本目は モンテカルロ資産シミュレーター の Scaling ベンチです。WebGPU は本当に最速か では、iPad mini で「約1万回を境に WebGPU が WebGL2 を逆転する」と書きました。条件は元記事の高負荷側、積立20年+取り崩し40年にそろえています。
| 試行回数 | WebGPU | WebGL2 | CPU | razr fold の最速 |
|---|---|---|---|---|
| 1,000 | 19.5 / 11 | 49.8 / 2 | 37.9 / 34 | WebGPU ※ |
| 5,000 | 8.3 / 5 | 4.2 / 4 | 127.1 / 103 | WebGL2 |
| 10,000 | 8.1 / 6 | 4.5 / 7 | 247.6 / 190 | WebGL2 |
| 50,000 | 19.5 / 23 | 17.6 / 25 | 1212.5 / 947 | WebGL2 |
| 100,000 | 17.7 / 32 | 29.0 / 32 | — / — | WebGPU |
※ 1,000回の WebGL2(49.8ms)は計測の最初の1回で、シェーダーのコンパイルなどの初回コストが混ざった値と考えられます。5,000回以降は 4ms 台に落ちています。
WebGL2 は互角以上、逆転点は10万回
WebGL2 は5千回から5万回まで iPad mini と同等か、それより速い水準です。一方で WebGPU が WebGL2 を上回るのは10万回になってからでした。5万回ではほぼ並び(19.5ms 対 17.6ms)、10万回で 17.7ms 対 29.0ms と抜けます。iPad mini の約1万回から、逆転点がひと桁遠くなりました。元記事で参考値として触れた「Pixel では1万回でも WebGL2 が勝つ」傾向が、さらに強く出た形です。
ただし10万回では、WebGPU 17.7ms に対して iPad mini は 32ms。大規模側では razr fold の WebGPU のほうが速いという結果です。
WebGPU は、試行回数にほとんど比例しない
WebGPU は1万回で 8.1ms、10万回で 17.7ms。仕事量が10倍になっても、時間は約2倍にしかなりません。1回の実行時間の大半が、試行回数と関係のない固定コスト、つまりパイプラインの準備と結果読み戻し(mapAsync)の待ちで占められていると考えられます。
実は最初の計測は、端末を再起動する前に行っていました。そのときの WebGPU は 20.4 / 8.5 / 42.2 / 17.1 / 21.5ms と、1万回だけ突出して遅く、試行回数と無関係に上下していました。再起動後は上の表のとおり、8〜20ms の範囲に収まっています。WebLLM の 1.5B が再起動を境に動くようになったのと同じく、端末の状態が GPU の計測値を大きく揺らしていた可能性があります。
単発実行の「同条件で CPU 実行して速度比較」でも、同じ1万回の WebGPU が再起動前は 25ms、再起動後は 58ms と、Scaling ベンチの値(8.1ms)と大きく違いました。各条件を1回ずつ測る方式では、この揺れを計算時間と区別できません。5回程度の中央値を取る、パイプライン生成を計測区間の外に出す、1回空打ちしてから測る。この3つで、固定コストと実計算を分けて見られるようになります。
CPU は iPad mini が少し上
CPU(JavaScript の逐次ループ)は、1万回で 248ms 対 190ms、5万回で 1213ms 対 947ms。iPad mini のほうが約1.1〜1.3倍速い結果です。差は大きくありませんが、全段で iPad mini が上回っています。
小さな演算では、iPad mini にまだ届かない
最後は TensorFlow.js バックエンド速度比較 です。乗り換え後に「ベンチマークでは iPad mini のほうがまだ上」と感じていた理由が、ここにいちばんはっきり出ました。
| 演算 | CPU | WebGL | WebGPU | razr fold の最速 |
|---|---|---|---|---|
| Dense (MatMul) | 7.80 / 5 | 9.60 / 8 | 9.20 / 3 | CPU |
| LSTM Cell | 4.80 / 2 | 21.10 / 98 | 18.20 / 12 | CPU |
| Conv2D | 20.40 / 4 | 12.60 / 9 | 6.40 / 2 | WebGPU |
| Softmax | 4.40 / 1 | 7.40 / 8 | 3.50 / 1 | WebGPU |
| Layer Norm | 1.90 / 1 | 11.20 / 8 | 4.70 / 1 | CPU |
ほぼ全項目で iPad mini が勝っています。razr fold が明確に上回ったのは、WebGL の LSTM Cell(21ms 対 98ms)だけです。なお、iPad mini 側の値は Safari のタイマー精度で1ms刻みに丸められているので、1〜2msの項目の倍率は目安です。
Dense は N=512 まで、一度も逆転しない
元記事では、iPad mini は N=64 付近で WebGPU が CPU を逆転しました。razr fold では N=512 まで一度も逆転せず、最後は CPU 約14ms に対して GPU 2方式は約33ms です。
注目したいのは左端です。GPU 2方式は N=32 でも4〜8msかかっています。演算量がほとんどないのに時間がかかる。つまり、演算量と関係のない固定コストが乗っています。モンテカルロの WebGPU で見たものと同じ構図です。
元記事の選択指針のうち、「小さい演算は CPU」は razr fold でむしろ強まりました。一方で「大きい Dense は WebGPU」は、少なくとも N=512 までの範囲では成り立ちません。バックエンドの自動選択は、固定の閾値ではなく、その端末での短い実測で決めるほうが安全です。
連続処理は強い、往復は遅い
4本の結果を並べると、razr fold の性格が3つの層に分かれて見えてきます。
| 層 | 評価 | 根拠 |
|---|---|---|
| GPUの連続処理 | 強い | WebLLM で 14.7〜29.3 tok/s、2B まで生成完走。描画は100万点でも上限張り付き。 |
| GPUへの往復 | 遅い | モンテカルロの WebGPU、TF.js の GPU バックエンドとも、結果の読み戻しを待つ数ms〜数十msが支配的。 |
| CPU単体 | iPad mini が上 | モンテカルロで約1.1〜1.3倍、TF.js で1.5〜5倍の差。 |
GPUに仕事を渡したまま回し続ける処理は速い。小さな仕事を1回ずつ投げて、結果を受け取る処理は遅い。この端末では、GPUそのものの速さより、GPUとの往復のコストが性能を決めています。
ベンチマークの数字では iPad mini が上なのに、体感は悪くない。その理由もここにあります。スクロールや描画、動画といった普段の操作は「往復」ではなく「連続処理」の側に属するからです。
過去記事の結論は、どこが入れ替わったか
| 過去記事の結論 | razr fold では |
|---|---|
| Android では WebLLM の体感が伴わない(2.6〜4.9 tok/s) | 14.7〜29.3 tok/s で実用域 |
| Qwen2.5-1.5B が最も安定 | 前日は生成エラー、端末再起動後の翌日は 18.1 tok/s で成功 |
| Qwen3-1.7B は多言語で崩壊 | 1回の出力では自然な日本語(要再検証) |
| 2B はメモリ上限超過(iPad mini) | 14.7 tok/s で生成完走 |
| Canvas 2D は100万点で 2〜11fps | 22fps |
| WebGPU は約1万回で WebGL2 を逆転(iPad mini) | 逆転は10万回 |
| Dense は N=64 付近で WebGPU が逆転(iPad mini) | N=512 まで CPU が最速 |
変わらなかったこと
- 大量の点を描くなら、GPU方式が CPU方式より桁違いに速い。
- 小さな演算では、GPU より CPU が速い。
- SVG は100万点では2〜3fpsで、どの端末でも実用にならない。
- どのバックエンドが最速かは、規模とハードウェアの組み合わせで決まる。
実機で測り直す、という当たり前
過去記事はどれも「実機で測って初めて分かる」と締めていました。今回の乗り換えで分かったのは、その結論自体も、端末が1台変わるだけで書き換わるということです。最適なモデルも、逆転点も、最速のバックエンドも、3台目では別の答えになりました。
変わらなかったのは個々の数字ではなく、設計の方針です。1つの方式に固定しない。フォールバックを持つ。閾値は実測で決める。制約から出発した設計は、端末が変わっても通用しました。
- WebLLM は 14.7〜29.3 tok/s。iPad mini で落ちた 2B も完走した。
- Qwen2.5-1.5B は前日に2度生成エラー、端末再起動後は 18.1 tok/s で成功。再現しない失敗だった。
- 描画は100万点でもGPU方式が上限張り付き。上限の90HzはOSの方針。
- モンテカルロと TF.js では、GPUへの往復コストが支配的で iPad mini に届かない。
- CPU単体は iPad mini が上(モンテカルロで約1.1〜1.3倍、TF.js でそれ以上)。
残した課題
- 1.5B の生成エラーが再発したときに、リモートデバッグでログを取る。
- Qwen3-1.7B の出力品質の再検証(質問を変えて複数回)。
- モンテカルロの計測を中央値方式に改め、WebGPU の固定コストを分離する。
- 長時間使った後の GPU 計測値の劣化が、再起動でどこまで戻るのかを確かめる。
- 1台体制になったことで失われた、Apple GPU / Safari での実機検証をどう補うか。