GPUの行列積はなぜタイル化するのか?warp・Shared Memory・Tensor Coreから理解する

GPUのtile化と行列積の全体像

GPUのtile化と行列積の全体像

ニューラルネットワークの多くの計算は、行列積として実行されます。

GPUはこの行列積を、巨大な行列のまま一度に処理するのではなく、小さなtile(部分行列)へ分割して処理します。

本記事では、thread、warp、SM、Shared Memory、Registers、Tensor Coreの関係から、GPUがなぜtile化でデータ再利用を制御するのかを整理します。

本記事の目的

GPUとNPU比較シリーズ前編の目的

本記事の目的は、GPUの行列積を「演算器がたくさんあるから速い」という説明だけで終わらせず、データ移動と再利用の観点から理解することです。

深層学習では、畳み込み、MLP、attention(入力間の関係を重み付けして集約する処理)など、多くの処理がGEMM(General Matrix Multiplication、汎用行列積)として実行されます。

しかし、演算器が多くても、A行列とB行列を遠いHBM/GDDRから毎回読み続けると、演算器へデータを供給できません。

GPUとNPUの違いも、演算器の数だけでは説明できません。

GPUは、SM(Streaming Multiprocessor、GPU内の実行資源)ごとにShared Memory(同じthread blockが共有するオンチップメモリ)とRegisters(threadごとの近接保存領域)を使い、tile化したA/Bを近い場所へ置いて再利用します。

後編では、NPU(Neural Processing Unit、ニューラルネットワーク向け演算器)のPE Array(Processing Elementの配列)、Systolic Array(データを隣接演算器へ流す配列構造)、On-chip SRAM(チップ上の高速メモリ)、データフローを扱います。

3文要約

GPU tiled GEMMの3文要約

GPUは、巨大な行列積を小さなtileへ分割し、A tileとB tileをShared MemoryやRegistersへ置いて複数の積和へ再利用します。

Registerは演算器ではなく、Tensor CoreやCUDA Coreへ渡す値、またはC tileの部分和を保持する近接保存領域です。

Tensor Coreへ継続的にデータを供給するには、HBM/GDDR、L2 Cache、Shared Memory、Registersをまたぐtile化とデータ移動の設計が重要になります。

論文・一次資料情報

GPU行列積解説で参照する一次資料

この記事は単一論文の要約ではなく、CUDAの実行モデル、Tensor Core、GPUメモリ階層を複数の一次資料から統合して説明します。

NVIDIA公式資料は公式アーキテクチャ資料・公式プログラミングガイドとして扱い、査読論文とは区別します。

種別 タイトル 著者・組織 この記事で参照する内容 リンク
技術論文 Scalable Parallel Programming with CUDA John Nickolls, Ian Buck, Michael Garland, Kevin Skadron 2008 CUDAのthread block、shared memory、warp、SIMTの基本概念 Scalable Parallel Programming with CUDA
論文 NVIDIA Tensor Core Programmability, Performance & Precision Stefano Markidis, Steven Wei Der Chien, Erwin Laure, Ivy Bo Peng, Jeffrey S. Vetter 2018 Volta世代Tensor Core、WMMA、CUTLASS、cuBLAS、MMAの位置づけ NVIDIA Tensor Core Programmability, Performance & Precision
公式ガイド CUDA Programming Guide NVIDIA 2026年版 CUDAプログラミングモデル、thread hierarchy、warp、memory model CUDA Programming Guide
公式ガイド CUDA C++ Best Practices Guide NVIDIA 2026年版 Shared Memoryを使った行列積、L2 Cache、Registers、occupancy CUDA C++ Best Practices Guide
公式チューニング資料 Hopper Tuning Guide NVIDIA 2026年版 Hopper世代のSM、occupancy、Tensor Core、TMAのチューニング観点 Hopper Tuning Guide
公式アーキテクチャ解説 NVIDIA Hopper Architecture In-Depth NVIDIA 2022 H100のSM数、L2容量、HBM、Tensor Core、Shared Memory/L1の容量例 NVIDIA Hopper Architecture In-Depth

本記事で容量例を出す場合は、主にH100 SXM5またはHopper世代の例として書きます。

たとえばNVIDIAのHopper解説では、H100 SXM5は132 SM、80GB HBM3、50MB L2 Cache、SMあたり256KBのcombined shared memory and L1 data cacheを持つ例として説明されています。

これはH100/Hopper世代の具体例であり、すべてのGPUに共通する固定値ではありません。

GPUの行列積とは:積和から理解する

行列積とMACの基本

ニューラルネットワークでよく出てくる行列積は、次の形で表されます。

\[ C = A \times B \]

ここで、Aは入力またはactivation(ニューラルネットワークの中間特徴)、Bはweight(学習済み重み)、Cは出力または部分和です。

各出力要素は、Aの行とBの列の積和で作られます。

\[ C_{i,j} = \sum_k A_{i,k}B_{k,j} \]

3×3の例で、\( C_{1,1} \) だけを見ると次のようになります。

\[ C_{1,1} = A_{1,1}B_{1,1} + A_{1,2}B_{2,1} + A_{1,3}B_{3,1} \]

MACはMultiply-Accumulate(乗算加算)の略で、\( A_{i,k}B_{k,j} \) を計算し、その結果をCの部分和へ足し込む処理です。

行列積で重要なのは、同じA/B要素が複数のC要素に関係することです。

たとえばAの同じ行要素は、Bの複数列と組み合わされ、複数のC要素に使われます。

Bの同じ列要素も、Aの複数行と組み合わされます。

そのため、行列積の性能は演算器のピーク性能だけでは決まりません。

A/Bをどこから読み、どれだけ近い場所に置き、何回再利用できるかが重要になります。

GPUの実行単位:thread、warp、thread block、SM

thread、warp、thread block、SMの関係

GPUの行列積を理解するには、まず実行単位の階層を分けて見る必要があります。

用語 初学者向けの比喩 技術的な説明
thread 小さな作業員 データの一部を担当する論理実行単位
warp 32人の作業班 NVIDIA GPUで基本的に同じ命令をまとめて実行するthread群
thread block 複数warpのチーム Shared Memoryを共有する実行単位
SM 作業場 warp、Register file、Shared Memory、演算器を持つ実行資源
Warp Scheduler 班を切り替える司令塔 実行可能なwarpを選び、レイテンシを隠蔽する回路
Tensor Core 行列積専用加工機 行列積和を高速に実行する演算器
CUDA Core 汎用加工機 スカラー演算やFMA(Fused Multiply-Add、乗算加算命令)などを実行する演算器
Register 作業員の手元 threadごとに割り当てられる近接保存領域

NVIDIA GPUにおいて、warpは通常32 threadsです。

ただし、threadやwarpはCPUのOSスレッドと同一ではありません。

CUDAのthreadは、カーネル内で同じプログラムを多数のデータに適用するための論理的な実行単位です。

thread blockは複数のthreadをまとめた単位で、同じblock内のthreadはShared Memoryを使って協調できます。

SMは、そのthread blockやwarpを実際に実行するGPU内の資源です。

SMの中には、Warp Scheduler、Register file、Shared Memory、CUDA Core、Tensor Coreなどがあります。

ここで特に誤解しやすいのがRegisterです。

Registerは演算器ではありません。

Registerは、Tensor CoreまたはCUDA Coreへ渡す値、A/Bの断片、Cの部分和などを保持する保存領域です。

実際のMACやMMA(Matrix Multiply-Accumulate、行列積和)は、Tensor CoreまたはCUDA Coreなどの演算器が実行します。

Tensor CoreとCUDA Coreも同じものではありません。

Tensor Coreは行列積和に特化した演算器で、CUDA Coreはより汎用的なスカラー演算や通常のFMAなどを担当します。

GPUのメモリ階層:HBM/GDDR、L2、Shared Memory、Registers

GPUメモリ階層の容量・共有範囲・近さ

GPUの行列積では、演算器そのものだけでなく、メモリ階層が重要です。

概念的には、次のような距離関係で考えると理解しやすくなります。

\[ \mathrm{HBM/GDDR} \rightarrow \mathrm{L2\ Cache} \rightarrow \mathrm{Shared\ Memory} \rightarrow \mathrm{Registers} \rightarrow \mathrm{Tensor\ Core / CUDA\ Core} \]

階層 役割 共有範囲 容量感 注意点
HBM/GDDR GPU外部またはパッケージ近傍の大容量メモリ GPU全体 大きい SMから見ると遠く、アクセスコストが高い
L2 Cache global memoryアクセスを緩和するキャッシュ GPU全体 HBM/GDDRより小さい 世代ごとに容量と挙動が異なる
Shared Memory block内の協調的なデータ再利用 SM内のthread block L2より小さい 明示的に使うscratchpadとして設計できる
Registers threadごとの値と部分和の保持 threadごと 小さい 使用量が多いとoccupancyに影響し得る
Tensor Core / CUDA Core 実際の演算 SM内 保存領域ではない 入力が継続供給されないと性能を出しにくい

一般に、容量は HBM/GDDR > L2 Cache > Shared Memory > Registers の順に小さくなり、演算器に近づくほど容量は小さく、アクセスは速くなります。

ただし、容量、帯域、レイテンシはGPU世代により異なります。

H100 SXM5の例では、HBM3が80GB、L2 Cacheが50MB、SMあたりcombined shared memory and L1 data cacheが256KBです。

これはHopper世代のH100 SXM5に関する例であり、他世代やコンシューマGPUへそのまま一般化してはいけません。

Register使用量、Shared Memory使用量、thread blockサイズは、occupancy(SM上に同時滞在できるwarpやblockの多さ)に影響し得ます。

CUDA Best Practices Guideでも、register fileはSM内の有限資源であり、register使用量が多いkernelではoccupancyが下がる場合があると説明されています。

重要なのは、GPUにもL2 Cacheが存在することです。

GPUは「キャッシュがないからtile化する」のではありません。

L2 Cacheが存在しても、行列積ではA/Bの再利用パターンが明確なため、Shared MemoryとRegistersを使って再利用を明示的に制御する価値があります。

GPUはなぜ行列積をtileへ分割するのか

GPU tiled GEMMのデータフローと再利用

GPUが行列積をtileへ分割する理由は、行列全体がRegistersやShared Memoryに入らないからです。

たとえば巨大なactivation行列Aとweight行列Bを、そのままSM内へ置くことはできません。

そのため、GPUはCの一部であるC tileを決め、そのC tileを作るために必要なA tileとB tileを順に持ち込みます。

流れは次のように整理できます。

  1. 行列全体はRegistersやShared Memoryに入らない
  2. A/Bを小さなtileへ分割する
  3. A tileとB tileをShared Memoryへ置く
  4. warp内のthreadが必要な断片をRegistersへ持つ
  5. Tensor CoreまたはCUDA Coreが積和を実行する
  6. C tileの部分和をRegister近傍に保持する
  7. K方向に次のA/B tileをロードし、同じC tileへ積和を続ける
  8. C tileが完成した後、HBM/GDDRへ書き戻す

ここでいうK方向とは、次の式の総和を取る軸です。

\[ C_{i,j} = \sum_k A_{i,k}B_{k,j} \]

C tileを完成させるには、K方向に並ぶ複数のA/B tileを順番に掛け合わせ、同じC tileの部分和へ足し込む必要があります。

このとき、A tileとB tileは一度Shared MemoryやRegistersへ置かれると、複数のC要素の計算に使われます。

遠いHBM/GDDRから読み込んだデータを、近いメモリ階層で複数回使うことで、遠いメモリアクセスのコストを償却します。

よくある誤解 正確な情報・解釈
GPUはキャッシュが無いからtile処理する GPUにもL2などのキャッシュはある。tile処理は、行列積に必要な再利用をより明示的に制御するために行う
Registerが積和を実行する Registerは保存領域であり、積和はTensor CoreまたはCUDA Coreが実行する
GPUは毎回DRAMから無駄にデータを読む 実際にはcache、Shared Memory、Registersで再利用する。ただし巨大行列ではtile入れ替えが必要になる
GPUは再利用しない GPUもtileを近いメモリに置いて再利用する
Tensor Coreだけ見れば性能が分かる Tensor Coreへデータを供給するShared Memory、Registers、レイアウト、同期、occupancyも性能に影響する

NickollsらのCUDA論文でも、shared memoryは低レイテンシのオンチップメモリとして、thread block内のデータ共有と再利用に使えることが説明されています。

CUDA Best Practices Guideでも、行列積におけるShared Memoryの利用は、global memoryから読んだデータをblock内で再利用する代表例として扱われています。

つまり、tile化は単なる分割ではありません。

演算器の近くにA/Bを置き、複数のMAC/MMAへ使い回すためのデータ移動設計です。

Tensor CoreとMMA:積和をどこで実行するのか

Tensor CoreとMMAの流れ

Tensor Coreは、行列積和を高速に実行する演算器です。

MMAはMatrix Multiply-Accumulateの略で、概念的には次の計算を表します。

\[ D = A \times B + C \]

ここでA/Bは入力断片、Cは累積済みの部分和、Dは更新後の出力断片です。

warp内のthreadは、A/B/Cの断片を分担して保持します。

Registersには、Tensor Coreへ渡す断片や部分和が置かれます。

しかし、Registerが積和を実行するわけではありません。

Tensor CoreがMMAを実行し、その結果が再びRegister近傍の累積値として扱われます。

Markidisらの2018年論文は、Volta世代のTensor Coreを対象に、WMMA(Warp Matrix Multiply-Accumulate、warp単位でMMAを扱うCUDA API)、CUTLASS、cuBLAS GEMMからTensor Coreを利用する方法を比較しています。

この論文ではVolta世代のTensor Coreについて、4×4行列に対するMMAを単位として説明しています。

ただし、これはVolta世代の説明です。

Tensor Coreの入力精度、累積精度、tile形状、命令形式は、GPU世代、データ型、命令セットに依存します。

Hopper世代では、FP8、FP16、BF16、TF32、FP64、INT8などのMMAデータ型が公式解説で紹介されています。

そのため、「Tensor Coreは常に4×4を計算する」のように一般化してはいけません。

Tensor Coreは、データが継続的に供給されなければ性能を発揮しにくい演算器です。

そのため、Shared Memory、Registers、tile化、メモリレイアウト、warp単位のデータ分担が重要になります。

大きい行列では、なぜtileの入れ替えを繰り返すのか

K方向のtile入れ替えループ

大きい行列では、C tileを一度決めても、それだけで計算は終わりません。

C tileを完成させるには、K方向の複数A/B tileを順に積和する必要があります。

概念的には次の更新を繰り返します。

\[ C_{\mathrm{tile}} \mathrel{+}= A_{\mathrm{tile},k} \times B_{\mathrm{tile},k} \]

行列全体をSM内に保持できないため、A/B tileはDRAM/HBMから順次ロードされます。

ただし、ロードしたtileをすぐに1回だけ使って捨てるわけではありません。

Shared MemoryとRegistersへ置いたtileは、複数の積和に使ってから入れ替えます。

重要なのは、DRAM/HBMから読み込んだデータを複数の演算に使い、遠いメモリアクセスを償却することです。

GPUは、HBM/GDDR、L2 Cache、Shared Memory、Registersというメモリ階層を通じて、Tensor CoreやCUDA Coreへデータを供給する方式です。

この見方をすると、GPUのtile化は「行列を小さく切るテクニック」ではなく、「近い場所で再利用して演算器を止めないためのデータ供給戦略」と言えます。

カメラAI・画像処理への応用

カメラAIと画像処理におけるGEMMとデータ移動

カメラAIや画像処理でも、GPUのtile化とデータ再利用は重要です。

DLNR(Deep Learning Noise Reduction、深層学習ノイズ除去)、Demosaic(ベイヤー配列などからRGB画像を復元する処理)、Super Resolution(超解像)、Transformer系画像処理では、畳み込みやattentionが内部的に行列積へ変換されることがあります。

畳み込みは、im2colのような変換やライブラリ内部の実装によりGEMMとして扱われる場合があります。

attentionでは、Query、Key、Valueの線形変換や \( QK^{\mathrm{T}} \)、attention重みとValueの積が大きな行列演算になります。

高ISOノイズ除去や高解像度化では、feature map(特徴マップ)やactivationが大きくなり、メモリ帯域が課題になりやすくなります。

GPU上で高速化するには、演算器のピーク性能だけでなく、A/Bに相当するactivationやweightをどう近い場所へ持ち込み、どう再利用するかが効いてきます。

実機搭載では、GPUだけでなく、ISP(Image Signal Processor、画像信号処理専用回路)、DSP(Digital Signal Processor、信号処理向けプロセッサ)、NPU、CPUとの役割分担が必要になる場合があります。

実際の性能は、モデル形状、精度、batch、入力サイズ、メモリ帯域、ライブラリ実装、データレイアウトに依存します。

そのため「Tensor Coreがあるから必ず速い」「NPUだから必ず省電力」といった単純な断定は避けるべきです。

まとめ

GPUは、SMの中でwarpがShared MemoryとRegistersを使い、A/BのtileをTensor Core近傍へ運んで再利用します。

行列全体が近いメモリに入らないため、K方向のtile入れ替えは必要です。

ただし、遠いHBM/GDDRから読み込んだA/B tileを複数の積和へ使うことで、データ移動のコストを償却しています。

Registerは積和を実行する場所ではなく、Tensor CoreやCUDA Coreへ渡す値と部分和を保持する場所です。

実際のMAC/MMAは、Tensor CoreまたはCUDA Coreが実行します。

GPUにもL2 Cacheはあります。

それでも行列積では、Shared MemoryやRegistersを使い、行列積に合った再利用を明示的に制御する価値があります。

GPUもNPUもデータ再利用を行いますが、再利用する場所とデータの流し方が異なります。

この違いが、後編で扱うPE Array、Systolic Array、On-chip SRAM、データフローの理解につながります。

関連技術

GPU tiled GEMMに関連する技術

技術 概要 本記事との関係
GEMM General Matrix Multiplication、汎用行列積 ニューラルネットワーク計算の中心
CUDA NVIDIA GPU向けの並列プログラミングモデル thread、block、Shared Memoryを扱う前提
Tensor Core 行列積和に特化した演算器 MMAを高速に実行する
WMMA Warp Matrix Multiply-Accumulate API warp単位でTensor Coreを使う抽象化
CUTLASS CUDA Templates for Linear Algebra Subroutines tile化GEMMやTensor Core利用の設計例
GPU memory hierarchy HBM/GDDR、L2、Shared Memory、Registersなど tile化と再利用を理解する軸
NPU ニューラルネットワーク向け演算器 後編でGPUとの違いを扱う
Systolic Array PE間でデータを流しながら再利用する配列 NPUの代表的なデータフロー
Dataflow accelerator データの流れを固定または制御して効率化するアクセラレータ GPUとの再利用方式の比較対象

次に読むべき記事

GPUとNPUの再利用方式の予告比較

後編では、NPUがどのようにデータを再利用するのかを、GPUとの違いから整理します。

後編の仮タイトルは次の通りです。

NPUはなぜDRAMアクセスを減らせるのか──PE ArrayとSystolic ArrayをGPUとの違いから理解する

後編の想定slugは、npu-systolic-array-dataflow です。

後編記事の想定URLは次の通りです。

NPUはなぜDRAMアクセスを減らしやすいのか?PE ArrayとSystolic ArrayをGPUとの違いから理解する
NPUのPE Array、Systolic Array、On-chip SRAM、FIFO、Accumulator、dataflowを、行列積の積和とA/B/Cの移動から解説。GPUのtile再利用との違い、DRAMアクセスを減らしやすい理由、カメラAI・エッジAIへの応用まで整理します。

後編レビュー時に、必要があれば最終URLまたは相対リンクへ調整します。

コメント

タイトルとURLをコピーしました