tiny-gpu アーキテクチャ概要
GPU
- 一度に1つのカーネルを実行するように構築
- カーネルを実行するには、次の作業が必要:
- カーネルコードをグローバルプログラムメモリにロード
- 必要なデータをデータメモリにロード
- デバイス制御レジスタで実行するスレッド数を指定
- 開始信号をHIGHに設定してカーネルを実行
- GPUは次のユニットで構成:
- デバイス制御レジスタ
- ディスパッチャ
- 可変数のコンピューティングコア
- データメモリおよびプログラムメモリ用のメモリコントローラ
- キャッシュ
メモリ
- GPUは外部グローバルメモリとインターフェースするように構築
- データメモリとプログラムメモリは簡略化のため分離
- グローバルメモリは固定の読み取り/書き込み帯域幅を持つ
- メモリコントローラは、コンピューティングコアからメモリへのすべての送信要求を追跡し、実際の外部メモリ帯域幅に応じて要求を調整し、外部メモリから適切なリソースへ応答を中継
- キャッシュは繰り返し要求されるデータを保存し、メモリ帯域幅の使用を削減
コア
- 各コアは計算リソースを保有
- 簡略化されたGPUでは、各コアは一度に1つのブロックを処理し、ブロック内の各スレッドに対して専用のALU、LSU、PC、レジスタファイルを持つ
- スケジューラはスレッド実行を管理し、ブロックを完了する前に新しいブロックを選択しない
- フェッチャは現在のプログラムカウンタから命令を非同期に取得
- デコーダはフェッチされた命令をスレッド実行用の制御信号にデコード
- 各スレッドは専用のレジスタファイルセットを持つ
- ALUはスレッドごとの専用算術論理演算装置
- LSUはグローバルデータメモリにアクセスするための、スレッドごとの専用ロード/ストアユニット
- PCは各スレッドで実行する次の命令を決定する専用プログラムカウンタ
ISA
- シンプルな11命令のISAを実装
- 行列加算や乗算などのシンプルなカーネル向けに構築
- 基本的な算術演算、メモリのロード/ストア、分岐、定数ロードなどをサポート
実行
- 各コアは命令を実行するために、フェッチ、デコード、要求、待機、実行、更新の段階を経る
- 各スレッドは、レジスタファイルのデータに対する計算を行うために実行パスに従う
- SIMD機能のため、読み取り専用レジスタにブロックインデックス、次元、スレッドインデックスの値がある
カーネル
- 行列加算および乗算カーネルをISAで記述し、SIMDプログラミングとGPU実行を実証
- テストファイルにより、GPU上でのカーネル実行を完全にシミュレーションし、データメモリの状態と実行トレースを生成できる
シミュレーション
- iverilogとcocotbをインストール後、
makeコマンドでカーネルシミュレーションを実行可能
- ログファイルに初期/最終データメモリ状態と、カーネルの完全な実行トレースが出力される
高度な機能
- 性能と機能を大きく向上させる現代GPUの多くの追加機能は、簡略化のため省略
- 多層キャッシュと共有メモリ、メモリコアレッシング、パイプライン化、Warpスケジューリング、分岐ダイバージェンス、同期やバリアなどの機能について議論
GN⁺の見解
- シンプルで分かりやすく、GPUアーキテクチャとSIMDプログラミングモデルの核心をうまく説明している。特に行列演算カーネルの例を通じて、実際のGPUでどのように並列処理が行われるのかをよく示している。
- 現代GPUで使われる高度な機能もよく整理されており、tiny-gpuを理解した後で、より複雑なGPUアーキテクチャを学ぶ助けになりそう。
- ただし実際のグラフィックスパイプライン機能は省かれているため、グラフィックスに特化したハードウェアがどのように動作するかは扱っていない。グラフィックスに関心のある人には物足りないかもしれない。
- オープンソースで公開されている他のGPUアーキテクチャであるMIAOWやGPGPU-Simなどと比較すると、より現実的なGPUを理解する助けになりそう。
- 今後、分岐ダイバージェンス、メモリコアレッシング、パイプライン化などの機能が追加されれば、さらに実用的な学習資料になることが期待される。開発に貢献できるオープンソースプロジェクトという点も魅力的。
1件のコメント
Hacker Newsのコメント
IntelはGPUに関する多くの技術文書を公開している。810/815のマニュアルもオンラインで見つけられる。855/910/915/945を除けば、文書化は一貫して行われている。
オープンコアGPUの取り組みを奨励したい。
NyuziProcessorという別のオープンソースGPUプロジェクトもある。(https://github.com/jbush001/NyuziProcessor)
FPGAを始めてみたいが、どこから手を付けるべきか把握しづらく、分野全体がとっつきにくく感じられる。
最終目標はLLM(Large Language Model)のためのアクセラレータカードを作ることだ。メモリオフロードの部分を除けば、このプロジェクトと似ている部分が多いはずだ。
順序回路の
alwaysブロックで non-blocking と blocking の代入演算子を混在させる理由について質問している。以前、VHDLで似たような作業をしたことがある。opencoresというサイトにはさまざまなオープンソースHDLプロジェクトがあった。今の時代、HPCレベルの大規模分散HDLシミュレータがあるのか気になる。最新GPUを使ってRTLレベルのシミュレーションを行うのは理にかなっている。
ハードウェアプロジェクトがオープンになるのは好きだ。ただし、これはSIMDコプロセッサと主張したほうがよいかもしれない。GPUであるためには、少なくとも何らかのディスプレイ出力があるべきだ。最近はNvidiaなどがグラフィックスアーキテクチャのサーバー専用派生版をGPUとして販売しているため、用語はやや緩くなっているが、GPU設計における「グラフィックス」の部分は依然として複雑さのかなりの部分を占めている。
ALUがハードウェアレベルでDIV命令を直接実装するのは一般的なのか疑問に思う。現代のCUDAコアのようなものでは実際の命令として使われているのか、それとも通常はソフトウェアエミュレーションなのか気になる。実際のハードウェアの除算回路はかなり面積を取るので、GPUのALUには入っていないと思っていた。Verilogで
DIV: begin alu_out_reg <= rs / rt; endと書くのは簡単だが、シリコン上ではかなりの面積を消費する。しかし、Verilogのシミュレーションしかしていない人にはそれが分からないかもしれない。グラフィックス機能を提供しない、また別の「GPU」。こういうものは別の名前で呼ぶべきだという意見。
スレッドが並列に処理され、各命令の後にすべてのスレッドが同じプログラムカウンタに「収束」すると仮定して単純化している。実際のGPUでは個々のスレッドが異なるPCに分岐できるため、branch divergenceが発生する。シリコンでGPUを作る前に、GPUプログラミングをしてみたほうがよさそうだ。SIMDですらない。(LEDを点滅させる回路を組み立ててCPUを作ったと主張した人と同じだ)