GPU(描画・並列計算)— 同じ計算を大量にこなす職人

上級の解説は準備中のため、上級の内容を表示しています。

概要 — まず全体をつかむ

中級では、GPUが多数の単純コアで同じ命令を一斉適用する SIMT と、それを支える VRAM の帯域 までを見ました。上級では、その実行モデルをスレッドの階層まで分解し、なぜメモリ待ちを隠せるのか、そしてどこで頭打ちになるのか(限界)を端から端まで掘り下げます。ここは GPU 内部の実行モデルと性能特性の深掘り を担当します。

CPU と GPU の設計思想の違い(レイテンシ重視 対 スループット重視)は GPU 中級CPU 上級で扱ったので、ここでは大量並列そのものの仕組みと限界に集中します。

アニメーション『CPUとGPU(少数万能 vs 大量並列)』を開く
CPU と GPU の違いコアの「数」と「使い方」が正反対CPU少数(数個)の万能で速いコアコア速い・万能コア速い・万能コア速い・万能コア速い・万能処理のしかた ── 順番に1つずつ仕事1仕事2仕事3コア(1つ)複雑な仕事を、順番に1つずつ処理GPU多数(数千)の単純なコア小さな単純コアが何千個も処理のしかた ── いっせいに並列で同じ計算×大量配って、全コアで同時に描画・AIなど「同じ計算の大量繰り返し」はGPUが得意

詳細 — 1段階ずつ追う

SIMT — スレッドの階層と実行モデル

GPU の並列は、ただコアが多いだけではありません。スレッドを階層にまとめ、束ごとに同じ命令で流すのが要です。

  1. スレッド(※1) — 最小の実行単位。1 スレッドが 1 要素分の計算を受け持つ
  2. ワープ/ウェーブ(※2) — スレッドを 32(あるいは 64)本ずつ束ねた単位。この束が同じ命令を共有し、別々のデータに一斉適用する(これが SIMT の実体)
  3. ブロック/スレッドグループ(※3) — ワープをさらにまとめた単位。同じブロック内は共有メモリ(オンチップの高速な作業場)と同期手段を持てる
  4. グリッド — ブロックの集まり。カーネル(GPU 上の関数)1 回の実行はグリッド全体に対応する

登場人物メモ(※の説明):

  • ※1 スレッド — GPU では極めて軽量で、数万〜数十万を同時に抱える前提で設計されている(CPU のスレッドより桁違いに軽い)
  • ※2 ワープ/ウェーブ — NVIDIA ではワープ、AMD ではウェーブフロント。命令を共有する最小の並列束
  • ※3 共有メモリ — ブロック内スレッドが読み書きを共有できる高速メモリ。VRAM より速く、再利用の受け皿になる

ポイントは、命令を共有する最小単位がスレッド 1 本ではなく「束」だということ。ここから、後述の分岐発散という限界が生まれます。

メモリ帯域とレイテンシ隠蔽

GPU の性能は「演算がどれだけ速いか」以上に、データを供給し続けられるかで決まります。

  1. GPU は外部メモリ(VRAM)へのアクセスに数百サイクルのレイテンシ(待ち時間)を抱える
  2. CPU はこの待ちを巨大なキャッシュと分岐予測・投機実行で削ろうとする(レイテンシを短くする発想)
  3. GPU は逆に、待ちが出たら別のワープへ切り替える。走らせるワープを大量に用意し、どれかが待つ間に別のどれかが走る(レイテンシを隠す発想)
  4. だから GPU は大量の並列度そのものが燃料になる。コアを埋めるだけのワープが無いと、待ち時間がむき出しになって遅くなる

登場人物メモ(※の説明):

  • ※1 レイテンシ隠蔽 — 待ち時間を短縮するのではなく、待つ間に別の仕事を差し込んで見かけ上ゼロに近づける手法
  • ※2 メモリ帯域 — 1 秒あたりに読み書きできるデータ量。数千コアへ供給し続ける GPU では、演算能力より帯域が先に頭打ちになりやすい
  • ※3 コアレスアクセス — 束の中の隣接スレッドが連続アドレスを読むと、1 回のメモリ取引で多くの有効データが取れる。バラバラだと帯域が無駄になる

つまり GPU は「速いコアで待ちを消す」のではなく「大量のコアで待ちを塗りつぶす」機械です。この設計ゆえに、帯域が足りないとコアが遊ぶという固有の弱点も抱えます。

GPGPU — 描画以外への転用

描画(グラフィックス)で磨いた大量並列は、汎用計算へ転用されました。これを GPGPU(General-Purpose computing on GPU)と呼びます。

  • なぜ行列・ベクトルが得意か — 行列積やベクトル演算は、要素ごとの積和が互いに独立。同じ命令を大量データへ一斉適用でき、SIMT の束にそのまま乗る
  • AI・機械学習 — 学習も推論も中身は巨大な行列積の連なり。だから GPU が主役になった
  • 書き方の APICUDA(NVIDIA 専用)や OpenCL(汎用)といったコンピュートシェーダ系の API で、画面描画を経ずに計算だけを走らせる

要は、「同じ計算 × 大量データ × 要素が独立」という形に落とせる問題ほど GPU が効きます。逆にこの形に落ちない問題は、次の限界に突き当たります。

大量並列の限界 — どこで頭打ちになるか

GPU は万能ではありません。上級の学びどころは、得意の裏返しがそのまま限界になることです。

  • 分岐発散(ダイバージェンス) — 同じワープ内で if の枝が割れると、ハードは各枝を順番に流し、実行しない側のスレッドはマスクされて遊ぶ。条件分岐が多いコードほど実効並列度が落ちる
  • メモリ律速(memory-bound) — 演算が空いているのに帯域が上限に張り付く状態。データ再利用を増やす・共有メモリに載せる・コアレスアクセスにする、で帯域あたりの有効データを稼ぐしかない
  • CPU↔GPU 間の転送コスト — 多くの構成で両者は別メモリ空間。データは PCIe などを介して往復する。並列で得する量が小さいと、この転送が利得を食いつぶし、CPU 単体より遅くなる
  • 逐次処理は苦手 — 前の結果を待つ依存が強い処理は、束で揃えられず並列にならない。ここは少数の高速コアを持つ CPU の領分。だから両者は役割分担し、CPU が制御とオフロードの指揮、GPU が大量並列の実行を担う

GPU を活かす条件は、裏返せばこの限界の反対側にあります。分岐が浅く/帯域に見合う再利用があり/転送コストを償却できるだけ大量で/要素が独立——この形に収まるほど、大量並列は本領を発揮します。

理解度チェック

そのまま解けます(成績は保存されません)。無料アカウントを作ると、学習の記録と進捗の山登りが始まります。

1. 小さな配列をCPU側で用意し、GPUで1回だけ軽い計算をして結果をCPUへ戻す処理が、CPU単体より遅くなった。最も疑うべき原因は?

2. SIMTで動くGPUのワープ(32スレッドの束など)の中で、if文により半分が真・半分が偽に分かれた。ハードウェアは何をするか?

3. GPUがメモリ待ち(数百サイクルのレイテンシ)を「隠す」主な仕組みはどれか?

4. あるGPUカーネルで、演算ユニットの利用率は低いのにメモリ帯域はほぼ上限に張り付いていた。この状態の呼び方と対処として適切なのは?

5. GPGPU(汎用GPU計算)で行列積やベクトル演算が特に速い、その本質的な理由に最も近いのは?

6. GPUの「共有メモリ(オンチップの高速な作業場)」の説明として正しいのはどれ?

7. GPUのSIMTでスレッドをまとめる単位を、小さいものから大きいものへ正しく並べたのはどれ?

8. NVIDIA のGPU上で画面描画を経ずに計算だけを走らせるために使う、同社専用のGPU計算APIの名前を答えてください。