期待のネット新技術
NVLinkが抱えるCache Coherencyの問題と、それを捨てたUALinkのアプローチ
Scale-up Network(2)
2026年8月4日 06:00
さて、前回に引き続き、NVLinkの話である。前回はVolta同士、およびVoltaとPOWER9の間でCache Coherencyが提供されたという話を紹介した。ただ、Volta V100は6MBのL2 Cacheを搭載する。この全量に対して完全なCache Coherentを提供するためには、L2の各エントリがどこのメモリを参照しているかを完全に把握する必要がある。
V100の場合Cache Line(キャッシュの管理単位)は128Bytesなので、トータルで49,152個分のアドレスの管理を行い、必要に応じてSnoopの処理を行う必要がある。これは当然オーバーヘッドが馬鹿にならないため、メモリ全体をSharedとしてCache Snoopingの対象とするのではなく、メモリの一部をShared領域とし、そこだけをCache Snoopingの対象とするccNUMA(cache-coherent NUMA)が実装された。
ccNUMAの仕組みとして登場したEGM
もっとも、V100の世代ではどのメモリをLocal扱い(つまりNUMA扱い)とし、どのメモリをCache Coherent対象(つまりUMA対象)とするかの制御は結構面倒であった。このあたりを楽に扱えるようにする仕組みとしてEGM(Extended GPU Memory)の仕組みが搭載されたのはV100の2世代後のHopperことH100の世代である。H100の世代ではGrace-Hopper(Grace CPUとHopper GPUが一枚のカードに密結合する形で搭載されている)という構成であり、次の4つが混在する(図01)。
- 自身(B)のLocal HBM3へのアクセス
- 同一カード上のGrace(A)のLPDDR5Xへのアクセス
- 別のカード上のHopper(C)のHBM3へのアクセス
- 別のカード上のGrace(D)のLPDDR5Xへのアクセス
EGMを利用することで、プログラマーからは面倒なメモリアクセスの制御が大分楽になった。といっても、4種類のメモリのどこを使うかでアクセスに要する時間が大きく変わるので、Remote MemoryとLocal Memoryの使い分けを気にしなければいけないことには変わりないのだが。
Snoop Cache(Snoop Filter)によるトラフィック削減
話を戻すと、V100世代ではSnoopingのコストは結構高いままだった。なので対策としてはSnoop対象となるMemoryの量を減らすしかない格好だった。Snoopingのトラフィックを減らす方法としては、Snoop Filterがよく知られている。
Snoopingは通常、自分があるメモリを書き換えた場合に、それを接続されている他のノードに対して通知するという形で実装される。図01で言えば、BがGPU HBM3を書き換えた場合、それをA/C/Dに通知するわけだ。
ただ、実際にBのGPU HBM3を参照しているのはBだけで、A/C/Dは参照していないとすると、そもそもSnoopingが必要ないわけだが、それをBは知ることができないから無駄にSnoopingのトラフィックが発生するわけだ。そこで、「そのメモリ領域を自分以外に誰がアクセスするか」をキャッシュの形で持たせるという技法が生まれた。
例えば、BのHBM3を誰も他のCPU/GPUがアクセスしていないなら、HBM3を書き換えてもSnoopingを行う必要がないわけだ。これをSnoop Cacheと呼ぶのだが、これをA~DのCPU/GPUに各々持たせるLocal Snoop Cacheと、EのNVLink Switchに持たせるRemote Snoop Cacheがある。
一般にはLocal Snoop Cacheの技法の方が一般的だが、これはそうでなくても足りないGPUのL2を更に圧迫する要因になることもあり、少なくとも現時点でNVIDIAのGPUにこれを実装したという情報はない。
ではどうするか? というと、EのNVLink SwitchにSnoop Cacheを実装する技法が「あり得る」。このケースでは、B→Aのアクセスに関してはEを経由しないために効果がないが、B→C/B→DのアクセスではEを通るため、ここでEはBがCなりDのメモリ領域を参照している(or 書き換える)ことを検出できる。そこで自身のSnoop Cacheにその情報を蓄えておき、仮にCないしDがBの参照領域を書き換えた場合、そのSnoopパケットをBに送り出す。
反対に、CやDがBの参照領域「以外」を書き換えても、そのSnoopingパケットはEがSnoop Cacheを参照して「伝達不要」と判断できるので、その場でパケットを破棄することが可能だ。こうすることで、CやDがSnoopingを行うことそのものは防げない(というか、それを防ぐとEが判断できなくなってしまう)が、それをAやB側に無駄に伝えることが防げるので、結果的にNetworkトラフィックに占めるSnoopingの比率を下げられるというわけだ。
NVSwitch Gen XからSnoop Cache非搭載? ポートが増えるほど実装困難になる欠点
もちろん、この技法には欠点もある。1つには、図01で言えばAとB、CとDの間のSnoopingのフィルタリングは当然できないことがある。ただまぁ、これは大きな問題ではない。
より大きな問題が他に2つある。それは、NVSwitchの動作が遅くなる(Snoopingのパケットが来た場合、Snoop Cacheを参照してその伝達の可否を決定する必要があるので、このSnoop Cacheの参照に時間がかかる)ことと、NVSwitchのポート数が増えると、それに連動してSnoop Cacheの容量も大型化する点だ。
次の図02は、世代ごとのNVSwitchとGPUの接続図である。初代NVSwitch(V100)~3代目(H100)まで、1つのNVSwitchに直接接続できるGPUは8つである。ところがV100は6MB L2だがA100は40MB、H100は50MBのL2キャッシュを持つ。Cache Lineのサイズは一貫して128Bytesだから、それぞれのL2がアクセス可能なメモリ領域のエントリ数は、このようになる。
- V100:49,152個
- A100:327,680個
- H100:409,600個
Snoop Cacheのエントリがそれぞれ4Bytesだとして、8GPU分で計算すると、それぞれ次のとおりSnoop Cacheを搭載する必要がある(なんで4Bytesかというと、例えばH100なら最大80GBのHBM3を搭載するから、アドレスだけで37bitになる。Page Sizeは4KBなので、128BytesのCache Line単位ではなくこのPage単位で管理したとしても25bit分のページ番号フィールドが必要になる。これに管理情報を加えるとおおむね32bit=4Bytesというあたりだろう)。
- NVSwitch Gen1:1.5MB
- NVSwitch Gen2:10MB
- NVSwitch Gen3:12.5MB
このあたりまではまぁ、実装はそう難しくないだろう。
では、Blackwellに接続されるNVSwitch Gen5で同じ計算をするとどうなるか? というと、まずBlackwellはダイあたり128MB、2ダイ合計で256MBのL2を搭載するから、利用可能なメモリ領域のエントリ数は2,097,152個。HBMの容量は最大288GBだから39bitアドレスが必要であり、ページ単位の保持であってもページ番号フィールドは27bitになり、そろそろSnoop Cacheの1エントリが32bitで収まるか怪しい。
一応32bitでギリギリ行けたとしても、最大72個のGPUを接続できるから、576MBものSnoop Cacheが必要という計算になり、これはいくら何でも無理がある。
このあたりもあってか、NVSwitchにSnoop Cacheが搭載されているかどうかはかなり怪しい感じになっている。実際のところ、第三者のドキュメントの中にはNVSwitchにはSnoop Cacheが搭載されていると記したものがあるが、公式のドキュメントを探してもNVSwitchにSnoop Cacheが搭載されていると明記されたものは存在しない。
可能性としては、Gen 2あるいはGen 3くらいのNVSwitchであれば搭載していても不思議ではない(これくらいなら無理なく実装できる)が、Gen 5世代の72ポート品ではまず無理だろうし、この先も実装されない公算が高いと思われる。
そして、適切なSnoop Cacheのようなメカニズムがない状態でCache Coherentを維持しようとすると、前回も説明したようにトラフィックが無駄に増えることになる。
Cache Coherencyを最初から諦めたUALink
NVIDIAはccNUMA構成で上手くCache Coherent対象となる領域を絞らせる(これをするのはプログラマー側の責任である)ことで、プログラミングの容易さとトラフィック増大のバランスを取ろうとしているが、このあたりをはなっから諦めたのがUALinkである。
図03はUALink 200 Rev 1.0 SpecificationのIntroductionであるが、ここにはっきりと"UALink does not support snoop transactions for keeping hardware coherence among Accelerators."と明示されている。
実は昨今のScale-up Networkは大体これであって、少なくともプロトコルレベルでのCache Coherencyは提供しないものばかりになっている。
これはある意味当然で、Cache CoherencyをサポートするためにはSnoopingは欠かせず、ところがSnoopingの実装には結構なコスト(Latencyの増加やSwitchの実装の複雑化、大容量SRAMの実装などに起因するSwitch製造コストの増大)がかかることを考えると、標準でそれを入れることには問題がある。
端的な話、完全なNUMAシステムのInterconnectであればそもそもSnoopingが発生しないから、それを仕様に入れるのはオーバーヘッドにしかならないという判断なのだろうと考えられる。
そんなこともあってか、現時点でCache CoherencyをサポートするScale-up NetworkはNVLinkのみに留まっており、それ以外のScale-up NetworkはCache Coherencyは提供されていない。ただそうなると、「ではScale-up Networkは従来のScale-out Networkと何が異なるのか?」という、前回の記事の冒頭の話に戻ることになる。次回はNVLink以外のScale-up Networkの話をご紹介したい。


