# Week 10：GPU性能とAI

## 今週のゴール

- GPUのメモリ階層とデータ移動コストを説明できる。
- coalescing、arithmetic intensity、occupancyを区別できる。
- 行列積がGPUやAIで重要な理由を説明できる。
- FP32、FP16、BF16、INT8の使い分けを精度・速度・容量から考えられる。

## 1. GPUのメモリ階層

単純化すると次の階層があります。

```text
thread private registers      最速・小さい
block shared memory / L1      同じblockで共有
GPU-wide L2 cache
global memory (VRAM)          大容量・高帯域・高レイテンシー
CPU system memory             接続越しの転送が必要な場合
```

GPUは演算器が多いため、必要データを十分な速度で供給できないと演算器が待ちます。計算だけでなくデータの場所と移動量が重要です。

## 2. coalescing

隣接threadが隣接アドレスへアクセスすると、ハードウェアが少数のメモリトランザクションへまとめやすくなります。

```text
良い例：thread 0→A[0], 1→A[1], 2→A[2]...
悪い例：thread 0→A[0], 1→A[1000], 2→A[2000]...
```

後者でも正しい結果は得られますが、多数の転送が必要になり帯域を有効利用しにくくなります。

## 3. 共有メモリで再利用する

global memoryから読み込んだデータをblock内の共有メモリへ置き、複数threadで再利用すると転送量を減らせます。

行列積では行列を小さなtileへ分割し、AとBのtileを共有メモリへ置いて複数の積和演算に再利用します。

## 4. Arithmetic intensity

転送1 byteあたり何回の演算を行うかという考え方です。

- intensityが低い：データを少し計算してすぐ捨てる。メモリ帯域に制限されやすい。
- intensityが高い：読み込んだデータを何度も計算に使う。演算性能を活かしやすい。

配列コピーは低く、うまくtile化した大規模行列積は高くできます。

## 5. occupancy

SMが保持可能な最大warp数に対し、実際に常駐しているwarpの割合を指す代表的な指標です。レジスタ、共有メモリ、block sizeなどで制約されます。

occupancyは高ければ常に最高性能というものではありません。十分に待ち時間を隠せた後は、データ再利用や命令効率など別の要因が支配します。

## 6. 行列積とAI

ニューラルネットワークの多くの処理は、行列積や畳み込みとして表せます。

```text
C[i,j] = Σ A[i,k] × B[k,j]
```

各出力要素には似た積和演算があり、データをtile単位で再利用できるためGPUに適します。

Tensor Coreなどの専用演算器は、小さな行列ブロックの積和演算を高いスループットで実行します。GPUのすべての命令がTensor Coreで速くなるわけではありません。

## 7. 数値精度

| 形式 | おおまかな特徴 | 主な用途例 |
|---|---|---|
| FP32 | 精度と範囲の標準的な均衡 | 科学計算、学習、一般GPU計算 |
| FP16 | 小容量・高スループット、範囲や精度に注意 | AI学習・推論 |
| BF16 | FP32に近い指数範囲、仮数精度は低い | AI学習 |
| INT8 | 整数、非常に小さく高速に扱いやすい | 量子化推論 |

低精度にすると、同じメモリ容量・帯域で多くの値を扱え、対応演算器のスループットも上がる場合があります。一方、丸め誤差、overflow、モデル精度への影響を評価する必要があります。

## 8. CPUとGPUの協調

典型的にはCPUがプログラム全体を制御し、GPUへkernelを起動します。

```text
CPU：入力準備 → GPUへ転送 → kernel起動 → 結果待ち → 後処理
GPU：大量の要素を並列計算
```

処理が小さすぎると、起動や転送の固定コストが計算時間を上回り、CPUだけの方が速いことがあります。

## 実習

```powershell
python exercises/performance_lab.py vector --size 1000000
python exercises/performance_lab.py branch --size 1000000
```

次の表を埋めます。実測はCPU上ですが、処理形状からGPU適性を考えます。

| 処理 | 並列性 | 分岐 | データ再利用 | 転送量 | CPU/GPUどちら向きか |
|---|---|---|---|---|---|
| 要素ごとの加算 |  |  |  |  |  |
| 小さい配列の加算 |  |  |  |  |  |
| 大規模行列積 |  |  |  |  |  |
| 逐次依存する探索 |  |  |  |  |  |
| 各要素で別経路の複雑な分岐 |  |  |  |  |  |

## 説明課題

「GPUはTFLOPSが高いので、どんなプログラムもCPUより速い」という主張を、転送、並列性、分岐、問題サイズの語を使って訂正してください。

## 小テスト

1. 隣接threadの隣接メモリアクセスをまとめることを何というか。
2. 転送byteあたりの演算量を表す概念は何か。
3. shared memoryを使う主な目的を一つ答えよ。
4. 行列積がGPUに適する理由を一つ答えよ。
5. 低精度形式を使う利点と危険を一つずつ答えよ。

[解答](../answers.md#week-10)

