ひとことで言うと
アクセラレータ構成とは、汎用CPUだけでなく、同じ種類の演算を大量に並列実行する回路と、そのデータを運ぶメモリ階層を組み合わせて処理量を稼ぐ設計です。深層学習ではGPUの多数の演算器、行列演算専用回路、低精度データ形式が主役になります。
CPUが少人数の熟練作業員に複雑な仕事を任せる現場なら、GPUは同じ手順を分担する大人数の作業員を並べる現場です。仕事を分けられる間は速い一方、材料を一人ずつ遠くの倉庫から取らせると、作業員の数ではなく搬送が全体の速度を決めます。
なぜ必要か
CPUは少数の強いコアで、分岐や逐次処理を短い時間で進める設計です。GPUは一つのスレッドを最速にするより、多数のスレッドへ命令を適用して命令スループットとメモリ帯域を稼ぐ設計です。CUDAではスレッドをブロックやワープにまとめ、ブロック単位の仕事を独立に実行できます。
ニューラルネットワークの全結合層や畳み込みは、入力の異なる要素に同じ積和を繰り返します。したがって、計算を小さなタイルに分けて多くのスレッドへ割り当てやすく、CPUの逐次的な強さよりGPUの並列スループットが効きます。ただし並列化できない処理や分岐の多い処理までGPU向きになるわけではありません。
| 処理の性質 | 向く構成 | 見る指標 |
|---|---|---|
| 同じ演算を大量のデータへ適用 | GPU・行列演算器 | 並列度と演算スループット |
| 分岐や逐次依存が多い | CPU | 単一スレッドの応答性 |
| データ再利用が少ない | メモリ設計の見直し | 帯域とアクセスパターン |
仕組み
行列積を とします。出力要素は
です。、 は入力行列の要素、 は出力要素、 は積和の長さです。各 は別々のスレッドに担当させやすく、同じ入力タイルを複数の計算で再利用できます。
GPUではスレッドがレジスタや共有メモリを使い、全スレッドがアクセスできるグローバルメモリとの往復を減らします。共有メモリへタイルを一度読み込み、ブロック内で再利用すれば、同じ値を何度もグローバルメモリから読む量を抑えられます。演算器が余っていても、データ転送が追いつかなければメモリ帯域が律速です。
Tensor Coreのような行列演算専用回路は、ワープ全体の協調で 型の積和を処理します。混合精度では入力を低精度にして転送量と演算コストを抑え、累積をより高い精度で行う構成を選びます。低精度化は常に安全ではなく、表現範囲や丸め誤差を確認する必要があります。
試験でどう問われるか
| 問われ方 | 正解に寄る条件 | 引っかけ |
|---|---|---|
| CPUとGPUの設計思想 | CPUは少数の強いコア、GPUは多数のスレッドのスループット | GPUは単一スレッドも常に速い |
| 行列積がGPU向きな理由 | 要素ごとの積和を大量に独立実行できる | 行列演算なら転送コストは無視できる |
| 性能が伸びない原因 | グローバルメモリ帯域、転送、アクセスパターンを確認 | 演算器の数だけで速度が決まる |
| 専用行列回路と混合精度 | 行列積を専用化し、低精度入力と累積精度を使い分ける | 低精度なら誤差は必ず問題にならない |
実装で確かめる
NumPyでも、行列積が「出力要素ごとの積和」であることと、データ型を低精度へ変えられることを確認できます。実機のGPU速度を測るコードではありません。
import numpy as np
rng = np.random.default_rng(0)
A = rng.normal(size=(2, 3)).astype(np.float32)
B = rng.normal(size=(3, 4)).astype(np.float32)
C = A @ B
manual = np.array([[sum(A[i, k] * B[k, j] for k in range(3))
for j in range(4)] for i in range(2)])
print(np.allclose(C, manual), C.dtype)
print((A.astype(np.float16) @ B.astype(np.float16)).dtype)
取り違えやすいもの
| 用語 | 切り分け |
|---|---|
| CPU | 複雑な逐次処理や分岐を少数の強いコアで処理する汎用プロセッサです |
| GPU | 多数のスレッドへ同じ型の処理を広げ、計算と帯域のスループットを狙います |
| TPU | 行列演算を中心に専用化したアクセラレータの考え方です。GPUの汎用的なスレッド実行と同一ではありません |
| Tensor Core | GPU内の行列積・積和を専用化した演算器です。GPU全体やメモリ階層の名前ではありません |
| メモリ帯域 | 単位時間に運べるデータ量です。演算性能が高くても、供給が遅ければ律速になります |
想起チェック
CPUとGPUは、何を最適化する設計か
CPUは少数の強いコアによる単一スレッドの応答性、GPUは多数のスレッドによる並列スループットです。
行列積で共有メモリを使う理由は何か
入力タイルをブロック内で再利用し、グローバルメモリからの読み出し量を減らすためです。演算器の追加だけでは帯域律速を解消できません。
混合精度で確認すべき二つの点は何か
低精度にした入力の表現範囲・丸め誤差と、累積をどの精度で行うかです。