GPU演算器にデータを供給するレジスタ
GPUは超マルチスレッドの超並列の高性能プロセサである。NVIDIAの「K40 GPU」に使用されている「GK110B GPUチップ」には単精度浮動小数点演算器が192×15=2,880個搭載されている。これらの積和(A+=B×C)演算を連続して実行し、最高性能を引き出そうとすれば、 1回あたりA、B、Cの3つの値を供給し、更新されたAの値を格納する必要がある。つまり、毎サイクル4×2,880=11,520個の32bitデータの読み書きが出来なければならない。これは46,480バイトであり、クロックが1GHzとすると46.48TB/sのバンド幅を必要とする。
この膨大なバンド幅を実現するため、NVIDIAのハイエンドGPUであるKeplerアーキテクチャの「SM(Streaming Multiprocessor)」は、64K個の32bitレジスタを持っている。
これは256KBの容量であり、GK110チップは15個のSMを集積しているので、合計では3,840KBの容量である。GK110チップに搭載されているレベル2キャッシュの容量は、1,536KBであるから、このレジスタファイル(多数のレジスタをまとめて、アドレスで選択してアクセスできるようにしたもの)は、GK110チップの中で最も大きな容量の記憶装置である。
そして、A、B、C 3つの値の読み出しポートと、更新されたAのための1つの書き込みポートを持つ3R1Wの構造のレジスタファイルが必要になる。
図3-16は通常の1RW(Read かWriteのどちらかができるポートを1個)のSRAMセルの回路である。中央の部分がインバータをループ状につないだラッチであり、ワード線をグランドにしてパストランジスタをオフにした状態では、この部分で1/0の状態を保持する。
読み出しの場合は、ワード線をVddに上げるとパストランジスタがオンになり、ラッチの状態が+と‐のビット線に読み出される。これを差動回路のセンスアンプで読み出す。書き込みの場合は、ワード線をVddに上げてパストランジスタをオンにして、+と‐のビット線に書き込む情報を与える。
ただし、トランジスタの強さには製造バラつきがあるので1/0どちらかの状態になりやすいということが起こる。パストランジスタが大きすぎる設計だと、読み出しの時になりやすい方の状態になってしまい、ラッチに記憶されているデータが反転してしまうことが起こり得る。また、パストランジスタが小さすぎると、偏りとは逆のデータの書き込みができないという問題が起こる。メモリセルを微細化するとバラつきが増え偏りも大きくなるので、微小なメモリセルは動作マージンが小さく、設計が難しくなっているが、これは横道の話である。
一方、レジスタファイルに使うセルは3つの読み出しと1つの書き込みが同時に実行できる必要がある。この3R1Wセルの回路の一例を図3-17に示す。情報を記憶するラッチと書き込み回路は図3-16とほぼ同じであるが、右側に3組の読み出し回路が付けられている。Readのワード線1、2、3をVdd に上げると、対応するReadビット線1、2、3にセルの状態を読み出すことができる。
なお、書き込み回路は‐のビット線を省き、その代わりにWriteビット線にゲートを接続したトランジスタを付けている。1RWのメモリセルの場合は、トランジスタが1個増えることで面積が増えてしまうが、3R1Wの場合はビット線が1本減る方が面積削減効果が大きいので、このような回路が用いられる。
特に、セルの大きさは、かなりの程度、配線の面積で決まり、縦方向と横方向の線の本数の積が問題になる。横方向に電源(Vdd)とグランド(Vss)線があるとすると、1RWセルは縦方向2本、横方向3本で、両者の積は6となる。一方、3R1Wセルは縦方向が4本、横方向が6本で、積は24となる。つまり、配線だけでセル面積が決まるという粗いモデルでは、3R1Wのセルは、1RWセルの4倍の面積を占めるという見積もりになる。
つまり、GK110チップのレジスタファイルはL2キャッシュの2倍以上の容量であるだけでなく、ビットセルの面積が(簡易な見積もりであるが)4倍と大きいので、5~8倍くらいのチップ面積を占めていると思われる。
NVIDIAのGPUでは、32スレッドをまとめてWarpと呼んでいる。なお、Threadは英語では縦糸であり、Warpは横糸である。GPUの命令実行の様子を織物の用語を使って表したもので、WarpはSFの宇宙船のワープではない。
64K個のエントリを持つレジスタファイルというのは膨大なレジスタ数であるが、Warpは32レーンで並列に実行されるので、1レーン分で見れば2Kレジスタである。そして、最大64個のWarpを切り替えて実行するので、この場合は1つのスレッドが使用できるレジスタ数は、平均32個ということになり、これはCPUコアのレジスタ数と同じである。
ただし、CPUの場合は、1つのスレッドが使えるレジスタ数は32個というように固定であるが、GPUの場合は1つのSMで同時並列的に動く全部のスレッドが必要とするレジスタ数の合計が64K個以下であれば、より多くのレジスタを使うことができるようになっていて、1つのスレッドが使えるレジスタ数は、NVIDIAのKepler GPUの場合最大63個、Maxwell GPUの場合最大255個となっている。
1つのワープに含まれる32スレッドは同じプログラムを実行する。これはある意味ではSIMD(Single Instruction Multiple Thread)方式の実行であるが、スレッドごとにアドレス計算を行ない、バラバラのアドレスをアクセスできるという点で、連続アドレスのデータしかアクセスできないSIMDとは異なる。また、スレッドごとに条件判定を行うので、スレッドごとに条件分岐の方向が異なる場合があるという点でもSIMDとは異なっており、この実行方式はSIMT(Single Instruction Multiple Thread)方式と呼ばれている。
なお、最近ではSIMDでもバラバラのアドレスをアクセスできるScatter/Gatherという機能をサポートしたり、マスクレジスタを設けて並列に実行する演算のそれぞれの実行/非実行を制御できたりするSIMDプロセサも増えており、SIMDとSIMTの機能的な差は小さくなってきている。しかし、Scatter/Gatherのアドレスのリストを作ったり、マスクを作ったりする手間が掛かるので、プログラミングの観点から言うとSIMTの方が使い易いと思われる。