私はスコットMcFarlingことにより、以下の論文は、詳細な回答を提供思う:
http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-TN-36.pdf
私が説明するようにコードを使用してみましょうし。
unsigned char tab[1<<TABLE_BITS];
パターン履歴表です。タブの各エントリは、2ビットの飽和カウンタを保持します。条件分岐の方向は、最終的には、カウンタのMSBによって決定されます。
u.direction_prediction (tab[u.index] >> 1);
我々は2ビット以上の代わりに、ちょうど1ビットのカウンタを使用する理由は、予測ミスを減らすために、パターンがより敏感にすることです。 2ビットカウンタがそれを防ぐことができるが、例えば、内部ループが次回に実行される
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
...
}
}
は、1ビット・カウンタは、分岐を誤予測します。
次は、パターン履歴テーブルで正しいパターンを見つける方法です。
単純な方法は、分岐アドレスをインデックスとして使用することです。しかし、異なるブランチ間の相関は無視されます。だからこそグローバルブランチヒストリーが導入されました(詳細はhttp://www.eecg.utoronto.ca/~moshovos/ACA06/readings/two-level-bpred.pdfを参照してください)。あなたのコードで
、
unsigned int history;
は、グローバル分岐履歴を保存支店歴史登録です。
その後、何人かは、インデックスとしてグローバル分岐履歴のと分岐アドレスを組み合わせることがちょうどそれらのいずれかを使用するよりも、より正確な予測につながることを見出しました。その理由は、グローバルブランチヒストリとブランチアドレスの両方がブランチパターンに影響するからです。 これらのうちの1つを無視すると、異なる分岐パターンがパターンヒストリテーブルの同じ位置にハッシュされ、衝突の問題が発生する可能性があります。
Gshareが提案される前に、Gselectというソリューションがあります.Gselectは、パターン履歴テーブルのインデックスとしてグローバルブランチヒストリとブランチアドレスの連結を使用します。
Gshareが提供するソリューションは
index = branch_addr XOR branch_history
のハッシュ関数であるこれはまさに、次のコードは何を意味するのかである:
u.index = (history << (TABLE_BITS - HISTORY_LENGTH))^(b.address & ((1<<TABLE_BITS)-1));
スコットMcFarlingの論文はGshareがどのように動作するかを示すために良い例を提供しますGselectより優れている:
- ブランチアドレス= 1111_1111グローバルブランチ履歴= 0000_0000
- 分岐アドレス= 1111_1111グローバル分岐履歴の= 1000_0000
我々は偏りを防止するために、以下のGselect戦略を使用することを想定します。
index = { {branch_addr[7:4]}, {branch_history[3:0]} }
Gshareを区別することができますしながらGselectは、両方のケースのため1111_0000が生成されます異なるパターン。
私が知る限り、Gshareは、衝突を取り除くための最良の解決策であることが判明しています。