メモリの壁を1から — なぜ演算より転送が高いのか
掛け算より、数を運ぶほうが高い。配線の充放電という物理から出発して、DRAMのレイテンシがなぜ縮まないのか、メモリ階層の桁、リトルの法則、マシンバランスとルーフラインまで。最後に、目の前のカーネルが計算律速か帯域律速かを自分で切り分けられるところまで持っていきます。
高いのは計算ではない
「計算が重い」という言い方を疑うところから始めます。2つの数を掛けるのは驚くほど安い操作で、高いのはその数を演算器の前まで運んでくるほうです。
理由は物理です。乗算はトランジスタ数千個の局所的な動作で、信号が動く距離はミクロン単位。一方メモリから値を取り出すのは、チップの端や外まで引き回された配線を電圧で駆動する行為です。配線を まで振るのに要るエネルギーは
は配線に付いた静電容量、 は振る電圧です。つまり、1本の線に信号を通す代金は「その線がどれだけ電気を溜め込む器か」と「どれだけ強く電圧を振るか」の2つだけで決まり、しかも電圧のほうは2乗で効く、ということです。 は配線の長さにほぼ比例するので、距離がそのまま値段になる。隣のレジスタから読むのと基板の向こうのDRAMから読むのとでは、同じ1語でもエネルギーが桁で違います。演算は安く移動は高い——この非対称が以降すべての土台です。
なぜDRAMのレイテンシは縮まなかったのか
演算側はトランジスタが増え、周波数が上がり、演算器が並びました。ところがDRAMのレイテンシは同じ勢いでは縮んでいません。この差が開き続ける現象がメモリの壁です。理由は構造にあります。
DRAMの1ビットはコンデンサ1個とトランジスタ1個です。読むにはワード線を上げてセルの電荷をビット線へ吐き出させますが、ビット線には何百ものセルがぶら下がって容量が大きく、電圧変化はごくわずか。センスアンプで増幅して0か1かを確定させます。しかも読み出しで電荷は失われるので(破壊読み出し)書き戻しが要り、次に備えたプリチャージも要る。
この手続きは微細化しても短くなりません。セルを小さくすれば電荷が減り、信号が弱まって検出がむしろ難しくなるからです。一方バンド幅は、I/Oを増やし転送クロックを上げダイを積層すれば増やせる。バンド幅は金で買えるが、レイテンシは買えない。 この非対称性が、以降のあらゆる工夫の動機です。
大きくて速いメモリが作れない理由
では、なぜ「大きくて速い」を1段で実現できないのか。容量を増やせば記憶素子は広い面積を占め、配線が長くなり、抵抗と容量が増えて信号が鈍ります。極端には光速すら効く。1 GHzの1周期に光が進むのは真空中でも約30 cmです。大きいものは原理的に遠い。 だから速い小容量と遅い大容量を積むしかありません。
| 階層 | 実現方式 | レイテンシの桁 | 容量の桁 |
|---|---|---|---|
| レジスタ | フリップフロップ | 1サイクル未満 | 数百バイト |
| L1キャッシュ | SRAM | 数サイクル | 数十KB |
| 最終段キャッシュ | SRAM | 数十〜数百サイクル | 数MB〜数十MB |
| 主記憶 | DRAM | 数百サイクル(数十〜100 ns級) | GB |
| 不揮発ストレージ | フラッシュ | 数万〜数百万サイクル | TB |
レイテンシは上から下まで6桁以上離れています。線形の目盛りに並べれば、上の数段は潰れて見えません。
レイテンシは隠せる、バンド幅は隠せない
レイテンシとバンド幅は別の量です。この2つを結ぶのが、待ち行列の一般則であるリトルの法則です。
は同時に飛んでいる未完了アクセスの数、 は達成したいスループット(毎秒のアクセス数)、 はレイテンシ。「欲しい流量 × 往復時間ぶんの在庫を、常に空中に浮かせておけ」と読みます。つまり、注文してから届くまでが遅い店ほど、そして速く売りたい店ほど、棚を切らさないためにはまとめて多く発注し続けるしかない、というのと同じ話です。64バイトのキャッシュラインを単位に毎秒1 TBを流したいなら 回/秒、レイテンシ100 nsなら 。常時1600件の読み出しが未完了のまま走っていないと、帯域は埋まりません。
プリフェッチも、ロードキューも、GPUが何万ものスレッドを走らせる設計も、この を確保してレイテンシを隠すための在庫です。ただし隠せるのはレイテンシだけで、運べる総量は帯域が決めます。ここから先が本題です。
コメント
コメントにはログインが必要です