+ 作る
図を読み込んでいます…
1 / 16
GPUとLLM:グラフィックボードはなぜAIを動かせるのか / 全5章

GPUの中身:数千のコアとメモリの階層

発行
かえで
版
第2版
改訂
分量
16コマ・4,719字

『GPUとLLM』第1章。画面のピクセルを塗る装置だったGPUが、なぜ大量の計算をさばけるのか。CPUとの設計の違い、SM・ワープ・スレッドの入れ子、Tensor Core、レジスタからHBMまでのメモリの階層を、NVIDIA H100 SXM の数値で見積もりながら、図が動く形で開いていきます。

GPUの中身:数千のコアとメモリの階層

グラフィックボードの心臓部であるGPUは、いまや大規模言語モデル(LLM)の学習や推論を支える計算装置になっています。この章では、GPUの中に何がどれだけ並んでいるのかを、外側から順に開いていきます。

図の左は小さな演算器がびっしり並んだチップ、右は大きさの違うメモリが積み重なった階層のイメージです。「とても多くの演算器」と「速さと容量の違うメモリの段々」の2つが、この章の主役です。具体的な数値は、データセンター向けの代表的なGPUである NVIDIA H100 SXM を例に使います。

  • 第1章
  • GPUの中身:数千のコアとメモリの階層
  • グラフィックボードの中に、何がどれだけ並んでいるのか
  • 小さな演算器がびっしり並んだGPUチップ
  • 数千のコア
  • メモリの階層
  • 『GPUとLLM:グラフィックボードはなぜAIを動かせるのか』

もとは、画面の点を塗る装置

GPUはもともと、画面の絵を描くための装置でした。画面は小さな点(ピクセル)の集まりで、フルHDなら 1920 × 1080 = 約207万個あります。1秒に60回描き直すなら、毎秒およそ1.2億個の点の色を計算しなければなりません。

図の赤い枠のマスも、その隣のマスも、使う式は同じ「色 = f(x, y)」で、違うのは入力の座標だけです。しかも、どのマスの計算もほかのマスの結果を待つ必要がありません。このように、同じ処理を大量のデータに一斉に当てはめる形をデータ並列と呼びます。GPUの設計は、この形を速くすることから始まっています。

  • もとは、画面の点を塗る装置
  • 16×9のマスに分けた画面。空・太陽・丘・草原の色
  • どのマスにも同じ計算 色 = f(x, y)
  • 1920 × 1080 = 約207万ピクセル
  • × 60回/秒 = 約1.2億回/秒
  • どのマスも、ほかのマスの結果を 待たずに計算できる
  • データ並列:同じ処理を、大量のデータに一斉に当てはめる

CPUとGPU:チップの面積を何に使うか

同じ大きさのシリコンでも、CPUとGPUでは面積の使い道が大きく違います。CPUは少数の高機能なコアに、命令を先読みしたり分岐の行き先を予測したりする制御回路(紫)と、大きなキャッシュ(青)を組み合わせます。1つの仕事をできるだけ早く終わらせるための作りです。

GPUは逆に、緑の小さな演算器を大量に並べ、制御とキャッシュは何個もの演算器でまとめて共有します。前のページのピクセルのマスが、そのまま右のGPUの演算器のマスに移ったように、データ1つ1つに演算器を割り当てるイメージです。サーバー向けCPUでもコアは数十〜数百個ですが、GPUの演算器は1万を超えます。

  • CPUとGPU:チップの面積を何に使うか
  • CPU
  • GPU
  • CPUの面積配分:制御、4つの大きなコア、大きなキャッシュ
  • GPUの面積配分:小さな演算器が8行×16列、行ごとに小さな制御とキャッシュ
  • コア
  • コア
  • 制御
  • コア
  • コア
  • キャッシュ
  • 制御
  • キャッシュ
  • 演算器
  • CPU:1つの仕事を早く終える工夫に面積を使う / GPU:演算器の数に面積を使う
  • 面積の割合は説明のための模式図です

待ち時間(レイテンシ)と処理量(スループット)

この違いは、何を速くしたいかの違いです。図は横軸を時間にして、各コアが仕事(緑の箱)をこなす様子を描いた例です。CPUは1件を時間1で終えますが、同時に進められるのは4件だけ。GPUは1件に時間4かかる代わりに、32件を同時に進めます。

一定時間に終わる量は「処理量 = 同時に進む数 ÷ 1件の時間」で決まり、この例ではCPUが 4 ÷ 1 = 4件、GPUが 32 ÷ 4 = 8件です。1件をすぐ返したい処理はCPUが、大量にさばく処理はGPUが得意になります。数字は説明用の例ですが、本物のGPUでは同時に進む数が数十万に達します(あとで計算します)。

  • 待ち時間(レイテンシ)と処理量(スループット)
  • CPUの小さな図
  • CPU:4つのコアがそれぞれ時間1の仕事を4件ずつこなす
  • CPU(4コア)
  • 1件の待ち時間 1 / 時間4で 4×4=16件
  • GPUの小さな図
  • GPU:32の演算器がそれぞれ時間4の仕事を1件ずつこなす
  • GPU(32演算器)
  • 1件の待ち時間 4 / 時間4で 32×1=32件
  • 時間 →
  • 0
  • 1
  • 2
  • 3
  • 4
  • 処理量 = 同時に進む数 ÷ 1件の時間 → CPU 4÷1=4、GPU 32÷4=8(時間1あたりの件数)

GPUの全体:SMが132個並ぶ

では、本物のGPUを開いてみます。NVIDIA H100 SXM のチップには、SM(ストリーミング・マルチプロセッサ)という処理の単位が132個並んでいます。図の緑のマス1つがSM1個です。SMはそれぞれが独立に命令を読んで動ける、小さなプロセッサのようなものです。

チップの中央には全SMが共有するL2キャッシュ(50MB)があり、チップの外、同じパッケージの上には HBM と呼ばれる積み重ね型のメモリ(合計80GB)が載っています。前のページの小さなGPUの図が、この全体図に広がりました。次のページでは、紫で囲んだSMを1つ拡大します。

  • GPUの全体:SMが132個並ぶ(H100の例)
  • SMが12列×11行=132個並んだチップ。中央にL2キャッシュ
  • HBM (メモリ)
  • L2キャッシュ 50MB(全SMで共有)
  • HBM (メモリ)
  • 緑のマス1つ=SM1個 ×132 / HBM3 合計80GB・3.35TB/s(H100 SXM、配置は模式図)

SMの中:4つの区画と専用の演算器

紫のSMを拡大すると、中は4つの区画に分かれています。各区画には、次にどの命令を出すかを決めるワープ・スケジューラ(紫)、計算途中の値を置くレジスタ(青、64KB)、32個のFP32演算器(緑のマス。CUDAコアとも呼ばれます)、そして行列計算専用のTensor Core(橙)が1つずつあります。

SM全体では FP32演算器が128個、Tensor Core が4個、レジスタが合計256KBです。下の共有メモリ/L1キャッシュは、同じSMの区画どうしで共有されます。H100全体の FP32演算器は 132 × 128 = 16,896個で、章の題名の「数千のコア」は実際には1万を超えています。

  • SMの中:4つの区画と専用の演算器
  • SM 1個(拡大)
  • SM 1個の中身
  • スケジューラ
  • スケジューラ
  • スケジューラ
  • スケジューラ
  • (H100 の例)
  • レジスタ 64KB
  • レジスタ 64KB
  • レジスタ 64KB
  • レジスタ 64KB
  • FP32演算器 128個
  • FP32演算器32個
  • FP32演算器32個
  • FP32演算器32個
  • Tensor Core 4個
  • レジスタ 計256KB
  • FP32 ×32
  • FP32 ×32
  • FP32 ×32
  • FP32 ×32
  • ワープを最大64個抱える
  • Tensor Core
  • Tensor Core
  • Tensor Core
  • Tensor Core
  • H100全体では FP32演算器が 132 × 128 = 16,896個
  • 整数やFP64の演算器、 読み書きの装置などは省略
  • 共有メモリ / L1キャッシュ 最大256KB(SMの中で共有)

ワープ:32スレッドが同じ命令を一斉に

GPUのプログラムは、たくさんのスレッド(1つの計算の流れ)として書きます。SMはスレッドを32本ずつ束ねたワープ単位で扱い、1つの命令をワープの32スレッドが一斉に実行します。前のページの緑の32マスが1列に並んだのが、ワープの姿です。

命令は同じでも、各スレッドは自分の番号 i に応じて別のデータ a[i]、b[i] を使います。これを SIMT(Single Instruction, Multiple Threads)と呼びます。下の段が GPU → SM → ワープ → スレッド の入れ子で、1つのSMは最大64ワープ(64 × 32 = 2,048スレッド)、H100全体では 132 × 2,048 = 270,336スレッドを同時に抱えられます。

  • ワープ:32スレッドが同じ命令を一斉に実行
  • 命令:c = a × b
  • ワープ
  • スレッド0
  • スレッド31
  • 命令は同じ。使うデータは、それぞれ自分の番号 i の a[i]、b[i]
  • GPU SM × 132
  • SM ワープ 最大64
  • ワープ スレッド × 32
  • スレッド 1つの計算の流れ
  • 1SMで 64ワープ × 32 = 2,048スレッド / H100全体で 132 × 2,048 = 270,336スレッド

ワープ内の分岐:両方の道を順番に通る

ワープの32スレッドは同じ命令を実行するので、if 文で行き先が分かれると困ったことが起きます。図では x[i] > 0 のスレッドが処理A(橙)、それ以外が処理B(紫)に進みます。ワープはまず橙のスレッドだけを動かして A を実行し、そのあいだ紫のスレッドは待ちます。次に紫のスレッドで B を実行し、今度は橙が待ちます。

下の2段のマスが、それぞれの番で動いているスレッドです。かかる時間は A と B の合計になり、どちらの番でも半分ほどの演算器が遊んでいます。32スレッドがそろって同じ道を通るときが、いちばん効率がよいということです。

  • ワープ内の分岐:両方の道を順番に通る
  • if (x[i] > 0) 処理A else     処理B
  • x[i] > 0 のスレッド → 処理A
  • x[i] ≤ 0 のスレッド → 処理B
  • ワープ
  • スレッド0
  • スレッド31
  • ① Aの番
  • Aの番:橙のスレッドだけが動き、ほかは待つ
  • ② Bの番
  • Bの番:紫のスレッドだけが動き、ほかは待つ
  • 色の濃いマス=その番で動くスレッド 灰色=待っているスレッド
  • かかる時間 = Aの時間 + Bの時間(32スレッドが同じ道なら、片方だけで済む)
  • → 同じワープのスレッドが同じ道を通るほど、演算器が遊ばない

メモリ待ちのあいだ、演算器は空いてしまう

32スレッドの束は、ここからは小さな箱「W0」として描きます。ワープがHBMのデータを読むと、届くまでに数百サイクルかかります。図は計算1に対して待ち3の長さで描いた例で、W0 は計算(緑)とメモリ待ち(灰)をくり返しています。

下の「演算器」の段を見ると、W0 が待っているあいだは赤い空きになっています。動いている割合は 計算 ÷(計算 + 待ち)= 1 ÷ 4 = 25% です。CPUなら大きなキャッシュで待ち時間そのものを縮めますが、GPUは別の方法でこの空きを埋めます。

  • メモリ待ちのあいだ、演算器は空いてしまう
  • W0
  • メモリ待ち
  • メモリ待ち
  • メモリ待ち
  • W0 がメモリを待つあいだ、ほかに実行できる 命令がなければ演算器は止まってしまう
  • 演算器
  • 時間 →
  • 動いている割合 = 計算 ÷(計算 + 待ち)= 1 ÷(1 + 3)= 25%
  • 赤いマス=演算器の空き。計算1に対して待ち3として描いた例(実際のHBMの待ちは数百サイクル)

別のワープに切り替えて、待ちを隠す

GPUのスケジューラは、待っているワープを脇に置き、すぐ実行できる別のワープの命令を出します。各ワープの値はもともとレジスタに置いたままなので、切り替えに保存や復元の手間はほとんどかかりません。図ではワープが4本に増え、W0 が待つあいだに W1・W2・W3 が順に計算して、下の段の赤い空きがすべて埋まりました。

必要なワープの数は、およそ 1 + 待ち ÷ 計算 で見積もれます。この例では 1 + 3 ÷ 1 = 4本です。SMが最大64ワープも抱えられるのは、数百サイクルの待ちでも切り替えで隠せるようにするためです。

  • 別のワープに切り替えて、待ちを隠す
  • ワープW0(32スレッドの束)
  • W0
  • メモリ待ち
  • メモリ待ち
  • メモリ待ち
  • ワープW1(32スレッドの束)
  • W1
  • W1の計算
  • W1のメモリ待ち
  • ワープW2(32スレッドの束)
  • W2
  • W2の計算
  • W2のメモリ待ち
  • ワープW3(32スレッドの束)
  • W3
  • W3の計算
  • W3のメモリ待ち
  • 演算器
  • 時間 →
  • 必要なワープ数 ≈ 1 + 待ち ÷ 計算 = 1 + 3 ÷ 1 = 4本 → 空きがなくなる
  • H100のSMは最大64ワープを抱えられる。待ちが長くても、切り替える相手がいれば隠せる

Tensor Core:小さな行列積を1命令で

FP32演算器は1サイクルに「積和」(掛けて足す c ← a × b + c)を1回行います。左の緑の四角が、これまで緑のマスで描いてきた演算器1個です。一方 Tensor Core は、小さな行列どうしの D = A × B + C をまとめて計算する専用回路です。図の青い行と紫の列を掛け合わせて足すと、D の橙のマスが1つ決まります。4×4の行列なら 4 × 4 × 4 = 64回の積和を命令1つでこなします。

H100 の Tensor Core は1個で1サイクルに約512回の積和(FP16、公表値からの逆算)をこなし、SM1個で比べると FP32演算器の16倍です(精度は違います)。わざわざ行列積専用の回路を積むのは、LLMの計算のほとんどが行列積だからです(第2章)。

  • Tensor Core:小さな行列積を1命令でまとめて
  • FP32演算器
  • Tensor Core
  • 行列D(4×4)
  • 行列A(4×4)
  • 行列B(4×4)
  • Bの1列
  • 行列C(4×4)
  • =
  • Aの1行
  • ×
  • +
  • Cの1マス
  • 1サイクルに 積和1回 c ← a × b + c
  • D
  • A
  • B
  • C
  • D[i][j] = Σ(k=1〜4)A[i][k] × B[k][j] + C[i][j]
  • 4 × 4 × 4 = 64回の積和を、命令1つで
  • H100(FP16):Tensor Core 1個は1サイクルに約512回の積和 SM1個あたり:FP32演算器 128回 / Tensor Core 4個 2,048回(16倍)
  • LLMの計算のほとんどは行列積 → だから専用回路を積む(第2章)
  • 図は4×4の例。実際の命令は16×8×16などの形を、ワープ(Hopperでは4ワープの組も)単位で扱う

メモリの階層:近くて小さい ↔ 遠くて大きい

演算器が計算するには、データを手元まで持ってこなければなりません。GPUのメモリは大きく4つの段に分かれていて、上の段ほど演算器の近くにあって速い代わりに小さく、下の段ほど大きい代わりに遠くて遅くなります。

いちばん上のレジスタは各スレッド専用の置き場で、1スレッドが使えるのは約1KBまで。共有メモリ/L1は同じSMのスレッドどうしで使う256KB、L2キャッシュは全SMで共有する50MBです。いちばん下のHBMはチップの外にある80GBのメモリで、LLMの重みはふだんここに置かれています。図の右側が、それぞれの段を誰と使うかと、その容量です。

  • メモリの階層:近くて小さい ↔ 遠くて大きい
  • 速い・小さい ↑
  • レジスタ
  • 各スレッド専用 1スレッドに 約1KBまで
  • 共有メモリ/L1
  • 同じSMのスレッドで共有 SM1個に 256KB
  • L2キャッシュ
  • 全SMで共有(チップの中) チップ全体で 50MB
  • HBM
  • チップの外(同じパッケージ) GPU全体で 80GB
  • ↓ 大きい・遅い
  • 上の段ほど演算器の近くにあって速いが小さい。下の段ほど大きいが遠くて遅い
  • 容量は H100 SXM の例(レジスタは1スレッドあたり最大255個×4バイト)

容量と待ち時間のトレードオフ

ピラミッドの段が、そのまま横向きのバーになりました。左の青いバーは容量で、長さは対数(同じだけ伸びるごとに10倍)です。レジスタの約1KBからHBMの80GBまで、1段下りるごとに100〜1,000倍ほど大きくなります。

右に伸びた橙のバーは、データを頼んでから届くまでの待ち時間(サイクル数)です。レジスタはほぼ待たず、共有メモリも約30サイクルですが、L2やHBMは数百サイクルかかります。そこでGPUのプログラムは、HBMから読んだデータを共有メモリやレジスタに置き、何度も使い回すように書かれます。待ち時間は同じHopper世代のGPUで測った例です。

  • 容量と待ち時間のトレードオフ
  • 容量(対数目盛り)
  • 待ち時間(サイクル)
  • レジスタ
  • 約1KB(1スレッドあたり)
  • ほぼ0(命令の中で読める)
  • 共有メモリ/L1
  • 256KB(SM1個あたり)
  • 約30
  • L2キャッシュ
  • 50MB(チップ全体)
  • 約260〜410(近い側〜遠い側)
  • HBM
  • 80GB(GPU全体)
  • 約650
  • 容量の大きい段ほど遠く、待ち時間も長い(速い段は小さい)
  • 容量:H100 SXM。待ち時間:同じHopper世代のH800 PCIeでの測定例(Luo et al., 2025)。 測り方や条件で変わるので目安です

ピーク演算性能を見積もる

GPUが1秒に何回計算できるかは「ピーク演算性能 ≈ SM数 × 1SMが1サイクルにできる演算数 × クロック周波数」で見積もれます。

H100 SXM で FP16 の Tensor Core を使うと、1SMは1サイクルに 4個 × 512 = 2,048回の積和、掛け算と足し算を別に数えて4,096回の演算をします。図の上の段のとおり 132 × 4,096 × 1.83×10⁹ ≈ 9.89×10¹⁴ で、1秒に約989兆回(989 TFLOPS)。NVIDIAの公表値と一致します。FP32演算器だけなら約67 TFLOPSで、Tensor Core が性能のほとんどを担っています。

下の灰色の帯は、前のページのHBMのバーが移ってきたものです。HBMが運べるのは1秒に3.35兆バイトです。

  • ピーク演算性能を見積もる(H100 SXM)
  • SMの数
  • 1SM・1サイクルの演算
  • クロック
  • ピーク演算性能
  • 132
  • ×
  • 4,096回
  • ×
  • 1.83GHz
  • =
  • ≈989 TFLOPS
  • チップに並ぶ SMの数
  • Tensor Core 4個 × 512積和 × 2(掛け算+足し算)
  • 1秒に18.3億サイクル
  • 1秒に約989兆回 (FP16・密な行列)
  • Tensor Coreを使わず FP32演算器だけなら:132 × 128 × 2 × 1.98GHz ≈ 67 TFLOPS(約15分の1)
  • HBMの帯域:3.35 TB/s = 1秒に3.35兆バイト運べる
  • 計算は1秒に約989兆回。運べるデータは1秒に3.35兆バイト
  • H100 SXM の公表値(FP16 Tensor・疎性なし 約989 TFLOPS、HBM3 3.35 TB/s)。クロックは公表値と整合する値

1バイト運ぶあいだに、約295回計算できる

2つの速さを割り算すると、989兆回/秒 ÷ 3.35兆バイト/秒 ≈ 295回/バイト です。HBMから1バイト届くあいだに、Tensor Core は約295回の演算をこなせます。左の青い1マスが届いた1バイト、右の橙のマス295個がそのあいだにできる演算です。

FP16の数は1個2バイトなので、読み込んだ数1個につき約590回計算しないと、演算器はHBMを待って遊んでしまいます。待つワープを切り替える工夫も、計算する仕事そのものが足りなければ隠しきれません。GPUは「計算は速いが、データを運ぶのが遅い」装置なのです。この比を算術強度として式にするのが第3章です。

  • 1バイト運ぶあいだに、約295回計算できる
  • そのあいだに Tensor Core ができる演算(1マス=1回)
  • 演算295回を表す橙のマス295個
  • HBMから届く 1バイト
  • 橙のマス 295個
  • 989兆回/秒 ÷ 3.35兆バイト/秒 ≈ 295回/バイト(FP16の数1個=2バイトなら約590回)
  • → 1つのデータで何回も計算しないと、演算器はHBMを待って遊ぶ(第3章)

まとめ

この章では、GPUの中を外側から順に開いてきました。要点は次の4つです。

  1. GPUは同じ処理を大量のデータに当てはめるデータ並列のために、チップの面積の多くを演算器に使い、待ち時間より処理量を重視している
  2. GPU → SM → ワープ → スレッド の入れ子で動き、ワープの32スレッドは同じ命令を一斉に実行する。メモリを待つワープは、別のワープに切り替えて隠す
  3. Tensor Core は小さな行列積 D = A × B + C をまとめて計算する専用回路で、ピーク性能のほとんどを担う
  4. メモリは レジスタ → 共有メモリ/L1 → L2 → HBM の階層になっていて、計算の速さに比べてHBMからデータを運ぶ速さが大きく足りない

次の第2章では、LLMが実際に何を計算しているのかを見ます。答えは「ほとんどが行列積」です。

  • まとめ:GPUの中身
  • 1. データ並列のための設計
  • 2. GPU → SM → ワープ → スレッド
  • CPU:少数の高機能コアで待ち時間を短く GPU:大量の演算器で処理量を大きく 画面の点を塗る「データ並列」から生まれた形
  • ワープの32スレッドは同じ命令を一斉に実行 分岐すると両方の道を順番に通る メモリを待つワープは切り替えて隠す
  • 3. Tensor Core
  • 4. メモリの階層
  • D = A × B + C を命令1つでまとめて計算 SMあたりFP32演算器の16倍の積和 H100のピーク約989 TFLOPS(FP16)を担う
  • レジスタ → 共有メモリ/L1 → L2 → HBM 下の段ほど大きく、遠くて遅い HBMが1バイト運ぶあいだに約295回計算できる
  • 次章:LLMは何を計算しているのか 中身のほとんどは行列積。Tensor Coreが活きる理由がそこで分かります
  • 『GPUとLLM』第1章 おわり

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]