#GPU#NVIDIA#WebGL#クラウド

H100を借りたのに、絵が1フレームも描けなかった — 計算GPUと描画GPUは別物


「GPU が必要」と言ったとき、実は 2 つの別々の話が混ざっています。

  • 計算用: 学習・推論。CUDA が動けばよい
  • 描画用: 3D レンダリング、ゲーム、映像制作。OpenGL / Vulkan / EGL が要る

同じ NVIDIA の GPU でも、片方しかできないものがあります。

3D アバターが動画配信プラットフォームへ 24 時間ライブ配信する、無人の AI アバター配信システムを作っていました。その過程で、この「計算用と描画用は別物」という壁に 2 回はまりました。CPU 描画で 1 回、MIG で 1 回。リソースが足りない話に見えて、実際には機能が無い話だった、という勘違いです。

以下は、実際にクラウド GPU を借りて測った結果から作った、描画用途の GPU 選定手順と、失敗の記録です。

やろうとしていたこと

構成はシンプルです。

ヘッドレス Chromium(3D アバターを WebGL で描画)
  → 画面と音声をキャプチャ
  → ffmpeg で H.264 + AAC にエンコード
  → RTMP で配信プラットフォームへ送出

LLM と TTS(音声合成)でアバターがしゃべり、それをブラウザで描画してエンコードし、そのまま流す。このうち「ヘッドレス Chromium で 3D を描く」部分をどこで動かすか、が最大の悩みどころでした。

ハズレ1: CPU 描画(SwiftShader)は解像度を下げても救えない

最初の設計では、renderer は CPU だけで動く前提でした。Chromium には SwiftShader という CPU 実装の WebGL バックエンドがあり、GPU がなくても WebGL は「動く」からです。

実測すると、確かに動きました。動いただけでした。素の WebGL は 60fps 出るのに、3D アバターのシーン(トゥーン系シェーダ + スキニング)は約 4fps

普通ならここで「解像度を落として軽くする」を試します。試しました。720p でも 540p でも 360p でも、4fps のまま変わりません。解像度に比例しないということは、律速がピクセル処理ではなくシーン処理そのものだ、ということです。設計書に用意していた「重かったら 540p / 24fps に降格」という保険は、最初から無効でした。

CPU 描画は不成立。GPU を用意することになりました。

ハズレ2: MIG スライスは「取れた」が「描けない」

手元のクラスタには H100 があり、MIG(Multi-Instance GPU)で 1g.10gb のスライスに分割して、LLM 推論や音声推論に配っていました。MIG は 1 枚の GPU を複数のインスタンスに分割する仕組みで、推論サービスを詰め込むには非常に有効です。ここに 1 枚借りれば追加コストゼロ。そう考えて、そこにレンダラーを載せようとしました。

検証 Pod を立てた結果はこうです。

  • Pod は正常にスケジュールされた(= スライスの空きはある)
  • Pod 内の nvidia-smi に H100 と MIG デバイスが見えている
  • それでも Chromium の WebGL は SwiftShader に落ちる

ここで「スライスが足りないのでは」と考えるのは自然ですが、違いました。Chromium のフラグをどう組み替えても、--use-gl=angle のバックエンドを egl にしても vulkan にしても、結果は同じ。Vulkan の ICD(ドライバ登録情報)を見に行くと、そもそも空でした。

原因は NVIDIA の公式仕様です。MIG は CUDA 計算専用で、グラフィックス API をサポートしていません。

これは性能の問題ではなく機能の有無の問題なので、スライスを何枚積んでも、最大の 7g.80gb を使っても、WebGL は 1 フレームも GPU で描けません。例えるなら、満車で停められないのではなく、そこは駐車場ではなく計算専用の部屋だった、という話です。空き枠を増やしても車は入りません。

「MIG を解除すればいいのでは」も筋が悪い

理屈の上では、MIG を解除して H100 を丸ごと 1 枚使えばグラフィックス API は通ります。ただし、データセンター向けの計算特化 GPU は、**描画に必要なユニットが削られています。**H100 の場合:

  • グラフィックス用の TPC が 2 基しかない(AI 計算のために描画ユニットを削ぎ落としたアーキテクチャ)
  • NVENC(ハードウェアエンコーダ)が非搭載

つまり、仮にグラフィックス API が通ったとしても描画性能は出ませんし、H.264 のハードウェアエンコードもできないので配信用途の旨みも薄い。運用上も、全スライスを推論サービスが使っている状態で MIG を解除するのは不可能でした。

カタログの CUDA コア数や VRAM 容量だけを見ても、この情報は出てきません。「高い GPU なら何でもできる」わけではない、というのがここでの学びでした。H100 は計算のための GPU で、絵を出すための GPU ではありません。

正解: 描画に対応した GPU をクラウドで借りる

最終的に、renderer だけをクラウドの描画対応 GPU に出しました。描画用途では、L4 / T4 / RTX 系のようにグラフィックスを想定して作られた GPUを選びます。RTX 4000 Ada / RTX 2000 Ada クラス(時間 $0.24〜0.28)で十分に 720p30 が出ました。高いほど良いわけではありません。

置き場所の設計はこうなりました。

処理 置き場所 理由
LLM・TTS・アプリケーション 手元クラスタ(H100 MIG) 計算タスク。MIG の得意分野
ブラウザ描画・エンコード クラウドの描画対応 GPU グラフィックス API が要る

**同じ「GPU が必要」でも、計算と描画は別の在庫として扱う。**これが今回いちばん大きな設計変更でした。

コンテナから本当に見えているか

GPU が割り当てられていることと、グラフィックスのドライバが使える状態であることは別です。描画対応 GPU を借りても、コンテナの設定次第でドライバが見えません。以下を確認します。

  • コンテナに NVIDIA_DRIVER_CAPABILITIES=all を指定する(既定値だとグラフィックス系のライブラリがマウントされない)
  • EGL の ICD(10_nvidia.json 相当)が置かれているか。eglinfo で NVIDIA の EGL デバイスが列挙されるか
  • Vulkan の ICD(icd.d/)が空でないか
  • libglvnd が入っているか

ここが揃っていないと、アプリケーションからは「NVIDIA の実装が存在しない」ように見えます。

「動いた」を信じない

これが実務上いちばん大事です。

**ヘッドレス Chromium は、GPU 描画に失敗すると黙って CPU 実装(SwiftShader)にフォールバックします。**エラーも警告も出ません。起動するし、WebGL コンテキストも取れるし、画面も出ます。遅いだけです。「動いている」を成功と読むと、本番直前まで気づけません。

判定は必ず出力側から取ります。

確認方法 CPU に落ちている 成立している
GL_RENDERER の文字列 SwiftShader NVIDIA
3D シーンの実測 fps 約 4 57〜58

10 倍以上違うので、迷いません。最小のプローブページ(GL_RENDERER と fps を出すだけ)を先に作ると、切り分けが劇的に速くなります。このスタックは失敗時に沈黙するので、fps か GPU 使用率で裏を取る、という一手間が効きます。

体数を決めるのは、たいてい CPU

「1 枚に何本乗るか」を実測したら、意外な結果が出ました。

項目 実測
同時配信数 4 本(720p30、実時間維持)
そのときの GPU 使用率 26%
先に飽和したもの CPU(16 vCPU)

GPU は 3 倍以上余っていました。理由は単純で、GPU の仕事は「描く」ところだけだからです。

処理 どこ
3D 描画 GPU
フレーム取り出し CPU / 転送
H.264 エンコード CPU(ソフトウェアの場合)
音声のミックス・mux・送出 CPU

だから NVENC の有無が体数に直結します。ハードウェアエンコードに逃がせば CPU が空き、もっと詰め込めます。GPU を選ぶときに vCPU 数とエンコーダの有無を見る、というのはここから来ています。

借り方: コミュニティ型とセキュア型、そして Stop の罠

安価な GPU クラウドには、個人・事業者が余剰 GPU を貸し出すコミュニティ型と、事業者が運用するセキュア型があります。

コミュニティ型は安い代わりに、**当たり外れがあります。**同じイメージ・同じ設定で、あるホストは 10 分間無事故、別のホストは 60〜150 秒ごとにクラッシュ、という差を実際に観測しました。

使い分けと、必ず入れるべき対策はこうです。

  • 開発中の実験 → コミュニティ型
  • 本番配信・長時間検証 → セキュア型
  • どちらでも、不良ホストを検知して引き直す仕組みを入れる(セキュア型でもホストは死にます)

もうひとつ、運用の罠を 1 つ。インスタンスを「Stop」すると、その GPU が他の人に取られて再開できなくなるサービスがあります。停止中も課金されるうえに再開できない、という最悪の状態になり得るので、使い終わったら Terminate が原則でした。

コストの出し方

時間 $0.28 × 720 時間/月 = $201.6/月(GPU 1 枚)
$201.6 ÷ 4 本 = $50.4/本 ≒ ¥7,600/本(150円/USD)

ここに乗る、見落としやすいものを挙げます。

  • 上り帯域: 2.5Mbps の送出で 1 日約 27GB。egress 課金のあるクラウド($0.09/GB 前後)だと月 1 万円規模の追加。GPU 専業クラウドは通信費込みのことが多い
  • 稼働時間の設計: 24 時間で ¥7,600/本、1 日 8 時間なら ¥2,500/本3 倍違います。「常時稼働が必要か」ではなく「どの時間帯に動かすか」の設計問題として扱う
  • 推論側のコスト: AI が 24 時間しゃべり続ける場合、LLM と TTS のコストがレンダラーを上回ることがあります

選定チェックリスト

描画用途で GPU を借りるとき、この順で確認しています。

  1. MIG か? → MIG ならグラフィックス API は使えない。検討終了
  2. graphics TPC と NVENC はあるか? → 計算特化 GPU(H100 など)は削られている。スペック表の「CUDA コア数」だけ見ても分からない
  3. vCPU は足りるか? → 体数を決めるのはたいてい CPU
  4. コンテナからドライバが見えるか?NVIDIA_DRIVER_CAPABILITIES=all、EGL/Vulkan の ICD、libglvnd
  5. 本当に GPU で描いているか?GL_RENDERER と fps で裏を取る。「起動した」は証拠にならない
  6. 不良ホストを引き直せるか? → コミュニティ型なら必須、セキュア型でも入れておく
  7. Stop ではなく Terminate になっているか? → 課金と再開可否を確認

まとめ

  • GPU は計算用と描画用で別カタログ。CUDA コア数や VRAM では判断できない
  • **MIG はグラフィックス API 非対応。**計算専用なので、スライス数に関係なく WebGL は動かない
  • 計算特化 GPU(H100 等)は graphics TPC が極小で NVENC も無い。MIG を解除しても描画には向かない
  • CPU 描画(SwiftShader)は 3D シーンでは実用にならず、解像度を下げても比例して軽くならない
  • **失敗が沈黙する。**CPU フォールバックを疑い、GL_RENDERER と fps で確認する
  • 体数を決めるのは CPU のことが多い。NVENC の有無が効く
  • コミュニティ型には当たり外れがある。引き直す仕組みを前提に置く
  • コストは稼働時間の設計で 3 倍変わる

「とりあえず一番強い GPU を借りる」が、いちばん外れやすい選択でした。用途に合った安いカードのほうが、速くて安いことがあります。「空きがなくて入らない」のか「そもそも入れない部屋なのか」を切り分けること。リソースが足りない話に見えて、機能が無い話だった、というのは GPU まわりでは案外よくある勘違いだと思います。

← 記事一覧へ