TT Lab
ブログ

한국어 English 日本語 中文

はじめる
ブログ

ブログ

バッチ処理と遅延:バッチサイズ、同時セッション、GPUの共有

ステータス:下書き(2026-10-16)、一部実測済み。 バッチごとの遅延は、自宅ラボの8GBクラスのノートPC向けGPU 1枚で、単発のPodとして測定しました(他のGPU作業なし、ウォームアップ後の繰り返しの中央値)。セッションのシミュレーションは、そのテーブルを用いたノートPCのCPUによる計算です(code/06_batching_sim.py、1秒前後)。実際のワーカーの同時セッション値は、TT Scoreパフォーマンスドキュメントの負荷試験(サーバーGPU、他の作業とカードを共有していた時点)から引用しました。 シリーズ「ビジョンモデルを読む 3」第6回。遅延とスループットの区別については、 第1回にあります。

目次

1. 直感:バスとタクシー

GPUは数千個の計算ユニットを持つバスです。乗客(入力)を1人だけ乗せて出発すると座席がほとんど空いてしまい、何人か集めて出発すると一度に多くの人を運べます。その代わり、集めている間、最初に来た乗客は待たされることになります。 バッチ処理とは、スループットを得るために遅延を犠牲にするトレードオフです。そして、バスがすでに満員である場合(1人だけで計算ユニットを使い切るモデルである場合)、さらに集めても得られるものはありません。

배치를 늘리면 처리량이 늘까 — 공 모델 실측 ① 512×288: 초당 처리한 창(높을수록 좋음) 0 25 50 75 100 1 4 8 12 16 배치 크기 FP16 102 72 FP32 66 44 ② 256×144: 창 하나에 드는 시간(낮을수록 좋음) FP32 배치 1 4.07ms FP32 배치 4 3.85ms FP16 배치 1 4.69ms FP16 배치 4 2.32ms 작은 입력은 GPU 가 놀아서 묶으면 이득, 큰 입력은 손해
図:バッチサイズを変更したときの1回あたりの処理時間と秒間処理フレーム数 — 入力512×288はバッチを増やしてもスループットが低下し、256×144は向上する

2. サーバー側の研究:遅延目標内でのバッチ化

これら3つをまとめると原則が見えてきます。 遅延予算が最初に決定され、バッチはその予算内でのみ大きくする。そして、どれほど効果があるかは、そのモデルとGPUで実際に測定してみなければ分からない。

3. 実際に測定してみる:空モデルはバッチ化すると高速化するのか

TT Scoreの空モデル(BlurBall、3フレームウィンドウ、パラメータ149万個)を実験用GPUでバッチサイズのみを変更して測定しました(512×288、ウォームアップ10回後、30回×3セットの中央値、cuDNN自動チューニング有効)。

バッチ FP16 1回 FP16 秒間フレーム FP32 1回 FP32 秒間フレーム
1 9.82ms 101.8 15.11ms 66.2
2 20.36ms 98.2 34.21ms 58.5
3 32.71ms 91.7 57.10ms 52.5
4 46.15ms 86.7 79.69ms 50.2
8 103.77ms 77.1 178.09ms 44.9
16 221.25ms 72.3 366.10ms 43.7

まとめるほどスループットが低下しました。 バッチ1がすでにこのGPUを使い切っているため、まとめると中間テンソルが大きくなり(512×288解像度を最後まで維持するモデルであるため、FP32の特徴マップ1つが数十MB)、キャッシュからあふれたものと推測されます(原因は推定)。長時間実行してGPUが熱くなって遅くなったわけでもありません。最も負荷の高い1024×576のバッチ4を数分間実行した後に再度測定したバッチ1は、最初の値と同じでした(9.77対9.82ms)。

入力を256×144に縮小すると、結果は逆になります。

256×144 バッチ1 バッチ4 フレームあたり(バッチ4)
FP32 4.07ms 15.40ms 3.85ms(0.95倍)
FP16 4.69ms 9.29ms 2.32ms(0.49倍)

小さな入力単体ではGPUに余裕があるため、4つをまとめることでFP16におけるフレームあたりの時間が半分になりました。同じモデルであっても、 入力サイズとGPUによってバッチの得失が逆転します。 2026-10-12にサーバーGPU(24GBクラス)で同じモデルを測定した際は、バッチ3がフレームあたり0.83倍(FP16 8.0ms → バッチ3 20.0ms)とわずかにメリットがありました(TT Scoreパフォーマンスドキュメント 2.9.8)。

4. 複数のセッションが1つのGPUを使用する場合

リアルタイムワーカーは、「リクエスト」ではなく「セッション」を受け取ります。セッションごとに30fpsでフレームが到着し、ワーカーはセッションごとに最新のフレームのみを保持します(第1回の「最新のみ」)。GPUが空いたら、待機中のセッションの最新ウィンドウを すべて1つのバッチにして 処理するのがTT Scoreワーカー方式です。上記の実測テーブルを代入して、セッション数ごとにシミュレートしました(GPUの割り当て分のみ、30秒)。

セッション 個別処理(最も古いフレームを優先) バッチ処理(待機中のセッションすべて)
ノートPC GPU実測テーブル、セッション3 セッションあたり30.0fps、遅延中央値9.8ms 同等
ノートPC GPU、セッション4 平均25.5fps(最も遅いセッション18.6)、中央値37.0・p99 43.0ms すべて21.7fps、中央値62.7・p99 79.1ms
ノートPC GPU、セッション6 平均17.0fps(最も遅いセッション2.5)、中央値39.3ms すべて13.5fps、中央値91.4ms
サーバーGPUテーブル、セッション5 平均25.0fps(最も遅いセッション5.1)、中央値36.0ms すべて30.0fps、中央値27.4・p99 40.0ms
サーバーGPU、セッション6 平均20.8fps(最も遅いセッション3.4) すべて26.3fps、中央値54.7ms

(code/06_batching_sim.out.txt(サーバーGPUテーブルはバッチ1・3の2点のみであるため、バッチ4以上は直線的に増加すると仮定しています。)

読み方は以下の通りです。

実際のワーカーの負荷試験(サーバーGPU、他の作業とカードを共有していた2026-10-11時点)も同様の傾向でした。単一セッションでは29.4fps・往復p99 32msであり、3セッションではセッションごとに16~20fps・往復中央値70~95msとなり、送信されたフレームの21~30%が新しいフレームによって上書きされて破棄されました(パフォーマンスドキュメント 4.2)。

5. GPUを共有する方法

複数のタスクが1枚のGPUを共有する方法には3つあります(NVIDIA GPU Operator・デバイスプラグインのドキュメント)。

方法 共有方法 メモリ分離 エラー分離
時分割(Time-Slicing) 交互に使用する。リソースが複数あるように「見せる」だけ なし なし
MPS 同時に実行、クライアントごとにメモリ・演算リソースの上限を設定 上限あり ドキュメントで確認できず
MIG(対応GPUのみ) ハードウェアレベルで分割し、インスタンスごとに専用メモリを持つ あり あり

時分割は手軽に見えますが、同じカード上の他のタスクが忙しいと、自身の遅延がそのまま増加します。Clockworkが指摘した「同時実行がテール遅延を拡大させる」という現象が、運用時にも発生している模様です。TT Scoreの実測値でも、同じ空モデルの1フレームあたりの時間は、カードがアイドル状態のときは10.5ms、他のタスク2~3個と共用しているときは34msでした(パフォーマンスドキュメント 2.9.8)。 リアルタイム遅延は、モデルそのものよりも「誰とカードを共用しているか」によって大きく左右されます。

6. 制限事項

7. 我々のプロジェクトとのつながり

次の記事は、サーバーではなく スマホ内 で実行するアプローチについてです。

ティティの一言。 バスがすでに満員なのにさらに人を乗せようとすると、ドアが閉まるのが遅くなるだけです。私の空モデルがまさにそれでした――まとめればまとめるほど遅くなったんですから!

参考文献

ログインするといいねできます

コメント

まだコメントはありません。

ログインするとコメントできます