スマホで小型 LLM を10分動かし続けると遅くなるのか。この端末では、生成速度に明確な低下は見られなかった(Qwen2.5 0.5B・1.5B)
スマホで小型の言語モデルを動かし続けると、途中から遅くなるのか。この記事では、その問いを自分の端末で確かめた。Qwen2.5 の 0.5B と 1.5B(どちらも Q4_K_M)を llama-bench で10分間連続で動かし、1分ごとの生成速度(tokens/s)と、同じ時間の温度・CPU 周波数の読みを記録した。モデルごとに5セット、計10セットだ。
この端末・この条件では、10分間の連続生成で生成速度が明確に落ちる様子は見られなかった。 0.5B は約20 tokens/s、1.5B は約10 tokens/s で、5セットの中央値は1分目から10分目までほぼ横ばいだった。10分目の中央値を1分目と比べた比は、5セットの中央値で 0.5B が 0.99、1.5B が 0.94 だった。落ちたと言えるのは電池駆動の 0.5B・2 の1セットだけで、そのセットは速度が大きく揺れていた。温度や周波数の読みとの関係は、速度が落ちていないので「同じ時間に落ちた」とは言えない。
測ったのは 2026-10-02 の1台の端末だけで、10分までの話だ。他の端末・他のモデル・もっと長い時間には当てはめられない。
何を確かめたか
最初の問いは次のとおりだ。
- スマホで小型 LLM を連続で動かし続けると、生成速度は何分ごろからどれだけ落ちるのか。落ちるとして、端末の温度の上昇と同じ時間に起きているのか。
測る前に、編集部は次の予想を記録していた(予備確認の前に、値を見ずに立てたもの)。
- 生成速度は最初の数分で下がり始め、10分後には最初の1分の中央値より1割以上低くなるのではないか。
- 大きいモデル(1.5B)の方が落ち幅が大きいのではないか。
この予想がどうなったかは、後の「予想に照らすと」の節に書く。
結果: 速度は10分間ほぼ横ばいだった
次の表は、セットごとの1分目と10分目の生成速度(その分に終わった測定の中央値)と、その比だ。「最後の3分/最初の3分」は、最初の3分間と最後の3分間(8〜10分)の測定をそれぞれまとめた中央値の比で、1分だけの値に左右されにくくするために付けた。「2〜9分の幅」は、途中の分ごとの中央値の最小〜最大だ。
| モデル・セット | 充電 | 1分目 | 10分目 | 10分目/1分目 | 最後の3分/最初の3分 | 2〜9分の幅 |
|---|---|---|---|---|---|---|
| 0.5B・1 | 電池 | 15.2 | 19.3 | 1.27 | 1.11 | 14.0〜20.4 |
| 0.5B・2 | 電池 | 22.1 | 15.2 | 0.69 | 0.67 | 4.7〜21.8 |
| 0.5B・3 | AC | 20.4 | 19.4 | 0.95 | 1.00 | 20.3〜20.6 |
| 0.5B・4 | AC | 20.3 | 20.1 | 0.99 | 0.99 | 19.5〜20.3 |
| 0.5B・5 | AC | 21.1 | 20.8 | 0.99 | 1.00 | 20.7〜21.2 |
| 1.5B・1 | 電池 | 10.5 | 9.0 | 0.85 | 1.01 | 9.1〜10.1 |
| 1.5B・2 | 電池 | 11.0 | 9.6 | 0.87 | 0.95 | 6.9〜10.5 |
| 1.5B・3 | AC | 10.2 | 10.0 | 0.97 | 1.00 | 9.9〜10.1 |
| 1.5B・4 | AC | 10.1 | 9.6 | 0.96 | 0.99 | 10.0〜10.1 |
| 1.5B・5 | AC | 11.2 | 10.5 | 0.94 | 0.99 | 10.0〜10.5 |
- 速度の単位は tokens/s(生成64トークン)。「充電」は各セットの開始時の状態で、どのセットも測定中に変わらなかった。
- 5セットの中央値(比)は、10分目/1分目が 0.5B で 0.99、1.5B で 0.94。最後の3分/最初の3分が 0.5B で 1.00、1.5B で 0.99。
1分ごとの生成速度を、5セットの中央値で結ぶと次のとおりだ。
線はどちらも右下がりになっていない。1.5B は1分目がやや高く(10.5)、2分目以降は 9.9〜10.1 で動き、10分目が 9.6 だった。10分目が9分目より低いのは、5セットのうち4セット(1〜4)だったが、10分目の測定は1セットあたり6〜8回で、これ以上は確かめていない。11分目以降は測っていないので、この低下が続くのかどうかは分からない。
「落ちた」と言える線
個々の測定は同じ条件でも揺れる。AC 接続のセットで、測定ごとの値のばらつき(標準偏差÷中央値)は 5〜12% あった。「1割」という線は1回の測定の揺れと同じ大きさなので、分ごとの中央値(1分あたり 5〜16回)で比べた。さらに、1分だけの値は揺れやすいので、次の両方を満たすときだけ「落ちた」と書くことにした(測定のあとに決めた線で、一般的な基準ではない)。
- 10分目の中央値が、1分目の 0.90 倍以下。
- 最後の3分の中央値が、最初の3分の 0.90 倍以下。
この線で見ると、落ちたと言えるのは 0.5B の2セット目だけだった(0.69 と 0.67)。ほかの9セットは、どちらか、または両方が 0.90 を超えている。AC 接続だった3〜5セットは、途中(2〜9分)の分ごとの中央値の幅が 0.1〜0.8 tokens/s と狭く、10分目の比は 0.94〜0.99 だった。
落ちたと言えるのは1セットだけ: 電池駆動の 0.5B・2
10分目が1分目より1割以上低かったのは、10セット中3セットだ(0.5B・2、1.5B・1、1.5B・2)。3つとも、電池駆動で測った1・2セット目に当たる。AC 接続のセットは6つとも1割未満だった。そのうち上の線(両方の比が 0.90 以下)を満たしたのは 0.5B・2 だけだ。
- 0.5B・2: 1分目 22.1 から10分目 15.2 へ下がった。3分目(16.6)までに下がり、5分目に 4.7 まで落ちたあとは 12.9〜15.2 で動いた。落ちたと言えるが、途中の分ごとの中央値は 4.7〜21.8 と大きく揺れていて、「一定の速さで落ち続けた」形ではない。このセットは測定中にプロセスが約 154MiB スワップ(メモリの退避先)に出ていた。揺れや低下の原因は確かめていない。
- 1.5B・1(0.85)・1.5B・2(0.87): 1分目が高いために比が下がっている。1.5B は5セットとも、1分目が全体の最大だった(1.5B・4 は途中の最大と同じ値)。最初の3分と最後の3分の比は 1.01 と 0.95 で、線を満たさない。1.5B・2 は4〜5分目に 6.9・7.6 まで落ちた分があり、6分目以降は 9.6〜10.5 で動いている。
0.5B・1 は逆に、1分目(15.2)が低く10分目(19.3)が高い(比 1.27)。電池駆動の2セットは、AC の3セットより速度の揺れが大きかった。セット内の測定ごとのばらつき(標準偏差÷中央値)は、0.5B で 1・2セット目が 19%・36%、3〜5セット目が 9〜11%。1.5B では 1・2セット目が 18%・20%、3〜5セット目が 5〜12%だった。ただし、電池駆動か AC かだけが違ったわけではない。1・2セット目は 03:26〜04:09 の測定で、3〜5セット目は 05:57 以降の測定だった(0.5B・2 は 05:42 の再測定で電池駆動)。測定中のスワップや、端末の他のプロセスの状況も同じではない(付録の表)。何が揺れを大きくしたのかは、このデータでは切り分けられない。
温度と周波数は、同じ時間に何をしていたか
速度が落ちていないので、「落ちた時刻と温度上昇の時刻が合うか」は確かめようがない。代わりに、速度が横ばいだった10分間に、読めた温度と周波数がどう動いたかを書く。
| 経過(分) | 0.5B 電池ゾーン(℃) | 0.5B CPU 系ゾーンの最大(℃) | 0.5B 周波数(MHz) | 1.5B 電池ゾーン(℃) | 1.5B CPU 系ゾーンの最大(℃) | 1.5B 周波数(MHz) |
|---|---|---|---|---|---|---|
| 1 | 36.9 | 53.9 | 1667 | 37.7 | 58.0 | 1773 |
| 2 | 37.0 | 54.8 | 1628 | 38.0 | 55.9 | 1488 |
| 3 | 37.3 | 53.8 | 1445 | 38.2 | 56.4 | 1505 |
| 4 | 37.5 | 54.5 | 1452 | 38.4 | 56.2 | 1504 |
| 5 | 37.7 | 54.0 | 1436 | 38.5 | 56.6 | 1536 |
| 6 | 37.9 | 54.9 | 1460 | 38.7 | 56.2 | 1478 |
| 7 | 38.0 | 54.3 | 1441 | 38.8 | 56.3 | 1535 |
| 8 | 38.0 | 55.0 | 1415 | 38.8 | 56.4 | 1468 |
| 9 | 38.1 | 54.3 | 1386 | 38.9 | 56.3 | 1504 |
| 10 | 38.1 | 54.4 | 1403 | 39.0 | 56.5 | 1475 |
- 各値は、その分の間に5秒ごとに読んだ値の平均を、5セットで平均したもの。電池ゾーンは
/sys/class/thermalのbattery。「CPU 系ゾーンの最大」は、名前がcpu-0-・cpu-1-で始まる16個のゾーンのうち、各時点で最も高い読み。周波数は CPU 0・1・4・5(この端末で使える4コア)のscaling_cur_freqの平均。
読み取れることは次のとおりだ。
- 電池ゾーンは、10分間で約1.2〜1.3℃上がった(0.5B: 36.9→38.1、1.5B: 37.7→39.0)。速度は横ばいだった。
- CPU 系ゾーンの最大は、ほぼ横ばいだった(0.5B: 53.9→54.4、1.5B: 58.0→56.5)。5秒ごとの読みの最大は、0.5B で 67.8℃、1.5B で 93.0℃(1.5B・1 の測定開始13秒後に1回だけ。5秒ごとの読みなので、その間の最大は分からない)。次に高かったのは 1.5B・5 の開始12.5秒後の 84.9℃ で、1.5B・2 にも 70.9℃・70.5℃ の読みがあった。中断線の 95℃ に近い読みは、93.0℃ と 84.9℃ の2回あったことになる。そのあとの分ごとの平均は54〜58℃前後だった。
- 周波数の平均は、1分目から10分目にかけて下がった(0.5B: 1667→1403、1.5B: 1773→1475)。ただし、30秒ごとの区間に分けて5セットを合わせた中央値は、10分間の20区間のうち、0.5B で19区間、1.5B で18区間が 1325 MHz だった。平均を押し上げていたと見られる 2.5GHz 超の読み(5秒ごとの読みのうち、10分までで0.5B が8回、1.5B が4回、いずれも5セットの合計)は、最初の2分に集中していて、3分目から10分までは0回だった。10分を過ぎた測定の終わり際には、1.5B のセット1に開始602秒後の読みが1回だけあった。
周波数の読みが下がっても速度は下がっていない。周波数の低下が熱によるものかどうか(サーマルスロットリングかどうか)は、この測定では確かめられていない。確かめられるのは、周波数の読みが最初の1〜2分で下がり、そのあと速度も温度の読みも大きく動かなかった、という並びだけだ。
読めた範囲と、読めなかったこと
- 温度:
/sys/class/thermalの zone 名は端末が出したままで、どのコア・部品に対応するかはメーカーの資料で確かめていない。電池ゾーンは、termux-battery-statusの temperature と、同じ時刻に両方を読めた全組で比べると、差は平均0.2℃、最大1.0℃だった。cpu-hw-trip-*という名前のゾーンは常に 105000(105℃ 相当)を返す。cpu-hw-trip-0(zone58)の trip_point_0_temp も 105000(測定後に読み直して確認)だったので、温度ではなくしきい値の表示と見て使わなかった(Linux カーネルの文書では、trip point は「The temperature above which trip point will be fired」)。 - 周波数:
scaling_cur_freqは、読んだ瞬間の値を5秒ごとに拾っただけだ。5秒の間の変化は見えていない。 - 端末の保護の仕組み: この端末の保護閾値は確かめていない。測定前に決めた中断条件(電池ゾーン 45℃ 以上、CPU 系ゾーン 95℃ 以上、電池残量 15% 未満)には、10セットとも当たらなかった。
予想に照らすと
記録しておいた予想と、測った結果を並べる。
- 「10分後には最初の1分の中央値より1割以上低くなる」: 全体としては支持されなかった。10分目/1分目の比は、5セットの中央値で 0.5B が 0.99、1.5B が 0.94。1割以上低かったのは10セット中3セットで、いずれも電池駆動のセットだった。AC のセットでは0.5B・1.5B とも1割未満だった。最初の3分と最後の3分の比も合わせて見ると、落ちたと言えるのは 0.5B・2 の1セットだけだった。
- 「最初の数分で下がり始める」: 1.5B は1分目(10.5)から2分目(10.1)にかけて少し下がり、そのあとは 9.9〜10.1 で動いた。0.5B の中央値は 19.4〜20.5 の間で、下がり始める分は見えなかった。
- 「1.5B の方が落ち幅が大きい」: 比の中央値は 1.5B が 0.94、0.5B が 0.99 で、向きは予想と同じだった。ただし、最初の3分と最後の3分の比では 1.5B が 0.99、0.5B が 1.00 でほとんど差がなく、1.5B は1分目が5セットとも最大で、その分だけ比が小さく出ている。「1.5B の方が大きく落ちる」とは言えない。
つまり、予想した「10分で1割以上落ちる」は、この端末の AC 接続の測定では起きなかった。電池駆動のセットでは落ちて見えたものがあるが、速度の揺れが大きく、スワップや時間帯も違うため、この測定だけでは原因を分けられない。
考察と、この結果の限界
ここからは測定結果をもとにした編集部の考えで、確認した事実とは分けて読んでほしい。
- この端末・この条件では、小さなモデルの生成速度は10分の連続使用の間、ほぼ一定だったと読める。a00012(短い測定)で測った 0.5B の約 19〜20 tokens/s(Q4_K_M・4スレッド)と、今回の1分目の値(約 20)は近く、10分たっても同じ水準だった。ただし a00012 は prompt の処理も含めた測定で、有効だった条件は少なく、直接の比較ではない。
- 速度が落ちない理由は確かめていない。周波数の読みが 1325 MHz の付近で動かなかったことと関係があるのかもしれないが、これは推測で、この測定では確かめられない。
- 電池駆動のセットで速度が大きく揺れたことと、充電状態の関係も確かめていない。充電状態のほかにも時間帯・スワップ・他のプロセスが違っており、因果は言えない。
限界は次のとおりだ。
- 1台の端末、10分までの結果。11分以降は測っていない。他の端末・他のモデル・他の量子化・他のスレッド数には当てはめられない。
- 測ったのは生成の速度だけ。
-p 0(prompt の処理なし)、生成64トークンを繰り返す条件で、実際に長い文章を生成し続けたときの速度ではない。1回あたりの測定は約2〜23秒(中央値は 0.5B で 3.2秒、1.5B で 6.4秒)で、測定の間にモデルの読み込みがある(測った生成は各セットの約83〜87%の時間)。 - 条件を制御できていない。室温は記録していない(電池ゾーンの開始時の温度は 34.1〜39.1℃)。充電状態は1・2セット目が電池駆動、3〜5セット目が AC 接続で、途中で充電器につながれた(つないだ時刻の記録は無い)。ほかのプロセスの負荷も制御できていない。
- 測定の中断があった。最初のスクリプトは 04:16 ごろ(0.5B の2セット目の途中)に止まったので、その分のログは使わず、残りを同じ条件・順序で 05:37 から回し直した(0.5B の2セット目は 05:42 に最初からやり直し)。測定した順序は、付録の表の開始時刻のとおりだ。
- 測定中も、測定を動かしている AI エージェントの実行環境と、30秒ごとの電池状態の取得が端末で動いていた。
測り方
- 端末・環境: a00012 と同じ。Android の Termux に PRoot で入れた Ubuntu 26.04、使える CPU は4コア(0・1・4・5)、llama.cpp 8681(Ubuntu のパッケージ、
llama-benchの表示は version 8681 (Debian))。 - モデル: Hugging Face の Qwen 公式 GGUF のうち、
qwen2.5-0.5b-instruct-q4_k_m.ggufとqwen2.5-1.5b-instruct-q4_k_m.gguf(a00012 で取得し、ファイルサイズと sha256 を API と照合したもの)。 - コマンド:
llama-bench -m <モデル> -t 4 -r 4 -p 0 -n 64 -mmp 0 -o jsonを、経過時間が10分になるまで繰り返し起動した。1回の起動で、モデルの読み込み、慣らし1回(llama-benchの既定)、測定4回が走る。a00012 の条件のうち、スレッド数は 4、生成は64トークン、-mmp 0(モデルをプロセスのメモリに読み込む)に合わせ、prompt の処理は測らない(-p 0)。 - 1分ごとの値: 測定ごとの終了時刻を、起動の終了時刻から測定の所要時間を引いて求め、その分に終わった測定の中央値を取った。1分あたりの測定回数は 0.5B で 5〜16回、1.5B で 6〜9回。セットの最後の起動は10分を少し過ぎて終わるので(セット全体で606〜646秒)、10分を超えた測定は1分ごとの値に入れていない。
- セット: モデルごとに5セット。0.5B→1.5B と 1.5B→0.5B を交互に並べた。セット間は最低5分の冷却を置き、電池ゾーンが測定前の基準(38.1℃)+1.5℃ 以内に戻るのを待った(上限15分)。
- モニタ: 5秒ごとに温度ゾーン・CPU 周波数・
llama-benchの VmSwap・VmRSS・VmHWM を、30秒ごとにtermux-battery-statusを記録した。 - 「落ちた」の判定: 上の「「落ちた」と言える線」のとおり。
付録: セットごとの測定条件
| セット | 開始(JST) | 充電 | 電池残量(開始→終了) | 開始時の電池ゾーン(℃) | プロセスのスワップ最大(MiB) | 開始時の空きメモリ(GB) | 1分あたりの測定回数 |
|---|---|---|---|---|---|---|---|
| 0.5B・1 | 03:26 | 電池 | 71→68% | 38.0 | 0 | 2.77 | 11〜15 |
| 1.5B・1 | 03:41 | 電池 | 67→64% | 39.1 | 170 | 2.69 | 6〜8 |
| 1.5B・2 | 03:59 | 電池 | 63→60% | 37.0 | 207 | 2.66 | 6〜9 |
| 0.5B・2 | 05:42(再測定) | 電池 | 46→42% | 34.1 | 154 | 2.46 | 5〜16 |
| 0.5B・3 | 05:57 | AC | 43→49% | 36.3 | 0 | 3.97 | 15〜16 |
| 1.5B・3 | 06:12 | AC | 54→60% | 37.9 | 163 | 2.70 | 7〜8 |
| 1.5B・4 | 06:28 | AC | 64→70% | 38.7 | 0 | 3.53 | 7〜8 |
| 0.5B・4 | 06:43 | AC | 74→80% | 38.8 | 0 | 3.66 | 14〜16 |
| 0.5B・5 | 07:03 | AC | 79→79% | 37.4 | 0 | 2.90 | 16 |
| 1.5B・5 | 07:18 | AC | 79→79% | 35.9 | 164 | 3.04 | 8〜9 |
- 空きメモリは、各セットの開始時の
MemAvailable(1GB は10億バイト)。端末全体では、測定前からスワップが使われていた(1・2セット目の前の使用量は約7.5GB。全体は約12.9GB)。 - スワップは
llama-benchのプロセスの VmSwap の最大。a00012 では、スワップに出た条件を無効にした。今回は無効にせず、全セットを表に載せた。スワップに出なかったセットだけに絞ると、0.5B は 1・3・4・5 の4セット(10分目/1分目は 1.27・0.95・0.99・0.99)で、落ちたセットは無い。1.5B は 1.5B・4 の1セットだけになる(比 0.96、最後の3分/最初の3分 0.99)。 - 測定は2026-10-02、03:26〜07:28(JST)。
出典
- 測定値(生成速度の1回ごとの値、温度・周波数・VmSwap・電池状態の記録)と集計: すべて筆者が 2026-10-02 に上の環境で実行して記録したもの。測定と集計は自作のスクリプト(
llama_sustained_bench.pyほか)で行った。 - a00012「スマホのLinux(Termux/PRoot)でllama.cppの生成速度を測った」(筆者の過去の記事。環境・モデル・a00012 の条件の参照元)
- Linux カーネルの ABI 文書「sysfs-class-thermal」(thermal_zone の temp・trip_point の単位が millidegree Celsius であること、取得日: 2026-10-02)
- termux-api のソース「BatteryStatusAPI.java」(
termux-battery-statusの temperature が摂氏であること、plugged の値、取得日: 2026-10-02) - llama.cpp「llama-bench」の README(tg の意味、
-rの繰り返し、JSON の1回ごとの値、取得日: 2026-09-26)