GPUとシェーダ — 数千コアが画素を同時に塗る

4K画面は約830万画素。リアルタイムCGはそれを毎秒60回以上塗り直します。1画素ずつ順番に計算していては絶対に間に合わない — だから「同じ計算を大量のデータへ一斉にかける」ことに特化した機械、GPUが生まれました。並列の威力と、その上で走る小さなプログラムシェーダを、動かして体感します。

1. なぜGPUは速いのか — 塗り競争で見る並列の力

絵作りの最終工程は「画素ごとに色をひとつ計算する」ことです。フルHDで約207万、4Kで約830万画素。60fpsなら毎秒約5億回の色計算になります。

CPUは少数精鋭 — 高クロック・分岐予測・巨大キャッシュを備えた高機能コアを数個〜十数個持ち、複雑で逐次的な処理が得意です。対してGPUは、単純な計算器を数百〜数千個並べます。画素の色計算は互いに独立なので、何万個に分割しても正しさが変わらない。だから「全員で同時に」が効くのです。下のデモで、1コアは速いが数が少ないCPUチームと、1コアは遅いが大人数のGPUチームに同じ絵を塗らせてみましょう。

塗り競争 — CPU 8コア vs GPU Nコア
同じ絵(1,296画素)を左右で塗り比べ。このデモではCPUコア1個はGPUコア1個の約4倍速い設定です。それでもコア数を増やすとGPUが圧勝し、逆に16コアまで減らすとCPUが勝ちます — 個の速さではなく並列度が勝負を決める領域があるのです。
T1フレーム ≈ (N / P) × t1画素 N = 画素数、P = 並列度、t1画素 = 1画素の計算時間。4K・60fps では毎秒約5億画素 — P を数千に上げて初めて間に合う
POINT — 並列化できる根拠は「画素の独立性」 ある画素の色を決めるのに、隣の画素の計算結果を待つ必要がない。この性質を持つ問題は embarrassingly parallel(自明並列)と呼ばれ、分割するだけで理論上コア数ぶん速くなる。ラスタライズもシェーディングもこの形をしているから、GPUという設計が成立する。

2. 絵ができる流れ — グラフィックスパイプライン

GPUの内部は流れ作業(パイプライン)です。頂点シェーダは頂点ごとに座標変換(レッスン2〜3の行列計算)を実行するプログラム。ラスタライザは三角形を画素の候補「フラグメント」に分解する固定機能回路(レッスン5)。フラグメントシェーダはフラグメントごとにライティングやテクスチャ(レッスン7〜8)で色を決めるプログラムです。

緑の箱がプログラム可能な段 — ここに開発者が自由なコードを書けることが、現代CGの表現力の源です。

パイプラインを流れる頂点とフラグメント
3個の頂点が頂点シェーダで変換され、ラスタライザで約50個のフラグメントに増え、フラグメントシェーダで1個ずつ色が付き、フレームバッファに書き込まれる。実際のゲームでは頂点数よりフラグメント数の方が桁違いに多いのが普通で、だからGPUの物量は主に画素側に注がれます。

3. フラグメントシェーダ — 全画素に同じ関数

フラグメントシェーダの正体は、画素の位置 (u, v) などを受け取って色を返す関数です。画面のすべての画素で「同じ関数」が同時に実行され、違うのは入力だけ。つまり関数を1つ書けば画面全体の模様が決まります。プリセットを切り替えて、その感覚をつかんでください。

ミニ・フラグメントシェーダ実験場 — 関数1つ=画面全体
左が「シェーダのコード」、右が1,620画素の出力。丸印を付けた画素AとBはまったく同じ関数を実行していて、結果が違うのは入力の (u, v) が違うから。波紋とプラズマは時刻 t も入力に取るので動き続けます。
color = f(u, v, t, …) GLSL では出力が gl_FragColor に相当。実際のシェーダは法線・テクスチャ・ライト位置など多くの入力(varying / uniform)を取る

4. SIMTと分岐ダイバージェンス — 数千スレッドの操縦法

数千のスレッドを1本ずつ独立に制御すると、制御回路だけでチップが埋まってしまいます。そこでGPUはスレッドを32本程度の束(NVIDIAはワープ、AMDは wavefront と呼ぶ)にまとめ、束の中の全レーンが同じ命令を一斉に実行します。この方式が SIMT(Single Instruction, Multiple Threads)です。

問題は if です。束の中で条件の真偽が割れると、GPUは両方の枝を順番に実行し、関係ないレーンをマスク(無効化)して待たせます。これが分岐ダイバージェンス — 並列機の隠れた弱点です。

1ワープ(8レーン)の実行タイムライン — if で道が割れると?
緑= if 側の命令、橙= else 側の命令、暗いマス=マスクされて待機中のレーン。スライダーを0か8にすると(全レーンが同じ道なら)片方の枝を丸ごとスキップでき、サイクル数が減って稼働率100%になります。混在すると両方の枝を直列に実行するため遅くなる。
俗説注意 — 「GPUは数千コアだからCPUの数百倍速い」ではない カタログの「CUDAコア数」などをCPUのコア数と直接比べるのは誤解のもと。GPUの「コア」は上で見たSIMTレーン(実行スロット)に近い存在で、独立した頭脳を持つCPUコアとは別物だ。分岐が入り乱れる処理・逐次依存の強い処理・レイテンシ重視の処理ではGPUは性能を出せない。CPUとGPUは優劣ではなく得意分野の分担である。

5. まとめ

一歩先へ — 絵を捨てたGPU:GPGPUと専用コアの時代 「独立した大量のデータに同じ計算」という形なら、絵でなくてもGPUは速い。物理シミュレーション・行列積・暗号など汎用計算に使う流れが GPGPU(CUDA やコンピュートシェーダ)で、深層学習ブームを支えたのはまさにGPUの行列積性能だった。近年はさらに、行列積専用の Tensor Core、レイと三角形の交差判定専用の RTコア など「特定の計算だけ桁違いに速い固定機能」を再び積む方向へ進んでいる — 次のレッスンで、そのRTコアが切り拓いた最前線を見に行こう。