バススヌーピングまたはバススニッフィングは、キャッシュ(スヌーピーキャッシュ)内のコヒーレンシーコントローラ(スヌーパー)がバストランザクションを監視またはスヌープする方式であり、分散共有メモリシステムでキャッシュコヒーレンシーを維持することを目的としています。この方式は、1983 年に Ravishankar と Goodman によって「ライトワンス」キャッシュコヒーレンシーという名前で導入されました。[ 1 ]コヒーレンシーコントローラ(スヌーパー)を含むキャッシュは、スヌーピーキャッシュと呼ばれます。
特定のデータが複数のキャッシュで共有され、プロセッサが共有データの値を変更すると、その変更はデータのコピーを持つ他のすべてのキャッシュに伝播されなければなりません。この変更の伝播により、システムがキャッシュの一貫性を侵害するのを防ぎます。データの変更の通知は、バススヌーピングによって行うことができます。すべてのスヌーパーは、バス上のすべてのトランザクションを監視します。共有キャッシュブロックを変更するトランザクションがバス上に現れると、すべてのスヌーパーは、キャッシュが共有ブロックの同じコピーを持っているかどうかを確認します。キャッシュが共有ブロックのコピーを持っている場合、対応するスヌーパーは、キャッシュの一貫性を確保するためのアクションを実行します。このアクションは、キャッシュブロックのフラッシュまたは無効化です。また、キャッシュの一貫性プロトコルに応じて、キャッシュブロックの状態の変更も含まれます。[ 2 ]
書き込み操作のローカルコピーを管理する方法に応じて、スヌーピングプロトコルには2種類あります。
プロセッサが共有キャッシュブロックに書き込むと、バススヌーピングによって他のキャッシュにあるすべての共有コピーが無効化されます。 [ 3 ]この方法により、プロセッサはデータのコピーを1つだけ排他的に読み書きできることが保証されます。他のキャッシュにある他のすべてのコピーは無効化されます。これは最も一般的に使用されているスヌーピングプロトコルです。MSI 、MESI、MOSI、MOESI、MESIFプロトコルはこのカテゴリに属します。
プロセッサが共有キャッシュブロックに書き込むと、バススヌーピングによって他のキャッシュの共有コピーがすべて更新されます。この方法は、書き込みデータをバス全体にわたるすべてのキャッシュにブロードキャストします。書き込み無効化プロトコルよりもバストラフィックが大きくなります。そのため、この方法は一般的ではありません。DragonプロトコルとFireflyプロトコルはこのカテゴリに属します。[ 4 ] [ 5 ]
考えられる実装例の一つは以下のとおりです。
キャッシュには3ビット追加されます。
各キャッシュラインは、次のいずれかの状態になります。「ダーティ」(ローカルプロセッサによって更新済み)、「有効」、「無効」、「共有」。キャッシュラインには値が格納されており、読み書きが可能です。キャッシュラインに書き込むと値が変更されます。各値は、メインメモリ(アクセスが非常に遅い)または1つ以上のローカルキャッシュ(アクセスが速い)に格納されます。ブロックが最初にキャッシュにロードされると、「有効」としてマークされます。
ローカルキャッシュへの読み取りミスが発生すると、読み取り要求がバス上でブロードキャストされます。すべてのキャッシュコントローラがバスを監視します。いずれかのコントローラがそのアドレスをキャッシュしており、そのアドレスが「ダーティ」状態である場合、状態を「有効」に変更し、要求元のノードにコピーを送信します。「有効」状態とは、キャッシュラインが最新であることを意味します。ローカル書き込みミス(その値を書き込もうとするが、キャッシュに存在しない場合)が発生すると、バススヌーピングによって、他のキャッシュにあるコピーがすべて「無効」に設定されます。「無効」とは、以前はキャッシュにコピーが存在していたが、現在は最新ではないことを意味します。
例えば、初期状態は次のようになるかもしれません。
タグ | ID | V | D | S --------------------- 1111 | 00 | 1 | 0 | 0 0000 | 01 | 0 | 0 | 0 0000 | 10 | 1 | 0 | 1 0000 | 11 | 0 | 0 | 0
アドレス1111 00への書き込み後、以下のように変化します。
タグ | ID | V | D | S --------------------- 1111 | 00 | 1 | 1 | 0 0000 | 01 | 0 | 0 | 0 0000 | 10 | 1 | 0 | 1 0000 | 11 | 0 | 0 | 0
キャッシュロジックはバスを監視し、キャッシュされたメモリが要求されたかどうかを検出します。キャッシュがダーティで共有されており、バス上でそのメモリに対する要求がある場合、ダーティスヌーピング要素が要求元にデータを提供します。その時点で、要求元がデータの責任を負う(データをダーティとしてマークする)か、メモリがコピーを取得する(メモリがデータを「スナーフした」と言われる)かのいずれかになり、2 つの要素は共有状態になります。[ 6 ]
ダーティとしてマークされたアドレスを無効化する場合(つまり、一方のキャッシュがダーティなアドレスを持ち、もう一方のキャッシュが書き込み中の場合)、キャッシュはそのリクエストを無視します。新しいキャッシュはダーティ、有効、排他的としてマークされ、そのキャッシュがアドレスの責任を負うことになります。[ 1 ]
バススヌーピングを使用する利点は、ディレクトリベースのコヒーレンシーメカニズムよりも高速であることです。共有されるデータは、ディレクトリベースのシステムでキャッシュ間のコヒーレンシーを維持する共通ディレクトリに配置されます。バススヌーピングは、すべてのトランザクションがすべてのプロセッサによって認識されるリクエスト/レスポンスであるため、十分な帯域幅があれば通常は高速です。[ 2 ]
バススヌーピングの欠点は、拡張性が限られていることです。キャッシュに対する頻繁なスヌーピングは、プロセッサからのアクセスと競合するため、キャッシュアクセス時間と消費電力が増加する可能性があります。各リクエストは、システム内のすべてのノードにブロードキャストする必要があります。つまり、システムが大きくなるにつれて、(物理的または論理的な)バスのサイズと、それが提供する帯域幅を拡張する必要があります。 [ 2 ]バススヌーピングは拡張性が低いため、大規模なキャッシュコヒーレントNUMA (ccNUMA)システムでは、ディレクトリベースのコヒーレンスプロトコルを使用する傾向があります。
特定のキャッシュブロックへのバストランザクションが発生すると、すべてのスヌーパーはそのバストランザクションをスヌープする必要があります。次に、スヌーパーは対応するキャッシュタグを検索し、同じキャッシュブロックが存在するかどうかを確認します。ほとんどの場合、最適化された並列プログラムはスレッド間で多くのデータを共有しないため、キャッシュにはそのキャッシュブロックは存在しません。したがって、キャッシュブロックを持たないキャッシュにとって、スヌーパーによるキャッシュタグの検索は通常不要な作業となります。しかし、タグの検索はプロセッサによるキャッシュアクセスを妨げ、余分な電力消費を引き起こします。
不要なスヌーピングを減らす方法の 1 つは、スヌープフィルタを使用することです。スヌープフィルタは、スヌーパーがキャッシュタグをチェックする必要があるかどうかを判断します。スヌープフィルタはディレクトリベースの構造であり、キャッシュブロックのコヒーレンス状態を追跡するために、すべてのコヒーレントトラフィックを監視します。つまり、スヌープフィルタはキャッシュブロックのコピーを持つキャッシュを認識します。したがって、キャッシュブロックのコピーを持たないキャッシュが不要なスヌーピングを行うのを防ぐことができます。スヌープフィルタの位置に応じて、フィルタには 3 つのタイプがあります。1 つはキャッシュ側に配置され、コヒーレンストラフィックが共有バスに到達する前にフィルタリングを実行するソースフィルタです。もう 1 つは受信キャッシュに配置され、受信コアでの不要なキャッシュタグのルックアップを防ぐ宛先フィルタですが、このタイプのフィルタリングではソースからの最初のコヒーレンスメッセージを防ぐことはできません。最後に、ネットワーク内フィルタは、共有バス内でコヒーレンストラフィックを動的に剪定します。[ 7 ]スヌープフィルタは、包括的と排他的に分類されます。包括的スヌープフィルタは、キャッシュ内のキャッシュブロックの存在を追跡します。一方、排他的スヌープフィルタは、キャッシュ内のキャッシュブロックの不在を監視します。言い換えれば、包括的スヌープフィルタでヒットするということは、対応するキャッシュブロックがキャッシュに保持されていることを意味します。一方、排他的スヌープフィルタでヒットするということは、要求されたキャッシュブロックがどのキャッシュにも存在しないことを意味します。[ 8 ]
{{cite book}}: CS1メンテナンス: 場所の発行元が見つかりません (リンク)