Vorhersagemechanismen in Fließbandarchitekturen

Transcription

Vorhersagemechanismen in Fließbandarchitekturen
Vorhersagemechanismen in
Fließbandarchitekturen
Projektarbeit im Wintersemester 2005/06
TU Darmstadt
FG Rechnerarchitektur
von Patrick Ediger
[email protected]
Betreuer: Prof. Dr. Rolf Hoffmann
Darmstadt, Januar 2006
Gliederung
1. Sprungvorhersage
Seite 1
1.1. Konflikte
Seite 1
1.2. Kontrollflusskonflikte minimieren
Seite 1
1.3. Statische Sprungvorhersage (static branch prediction)
Seite 2
1.4. Dynamische Sprungvorhersage (dynamic branch prediction)
Seite 2
1.5. Adaptive Sprungvorhersage (adaptive branch prediction)
Seite 5
1.6. Kombinierte und hierarchisch organisierte Sprungvorhersageverfahren
Seite 7
2. Sprungzielvorhersage
Seite 9
3. Wertvorhersage
Seite 10
3.1. Konstante Wertvorhersage (last value prediction)
Seite 10
3.2. Differentielle Wertvorhersage (stride prediction)
Seite 11
3.3. Kontextbasierte Wertvorhersage (context based prediction)
Seite 11
3.4. Wertvorhersage als Instrument für Sprungvorhersage
Seite 11
4. Literatur- und Abbildungsverzeichnis
Seite 12
1. Sprungvorhersage
1.1. Konflikte
Bei der Fließbandarchitektur (pipelining architecture) durchläuft ein Maschinenbefehl mehrere
hintereinander geschaltete Einzeloperationen (Stufen). Dabei kann sich in jeder Stufe ein Befehl
befinden, so dass sich bei einem Fließband mit n Stufen gleichzeitig n Befehle in der Verarbeitung
befinden. Im Optimalfall verlässt also auch pro Takt ein Befehl das Fließband. Es gibt allerdings
Konflikte, deren notwendige Beseitigung diese optimale Ausnutzung nicht mehr zulässt.
Man unterscheidet drei Arten von Konflikten: Betriebsmittelkonflikte (structural hazards),
Datenflusskonflikte (data hazards) und Kontrollflusskonflikte (control hazards)1. Ein
Betriebsmittelkonflikt tritt auf, wenn mehrere Befehle gleichzeitig auf die gleiche Ressource (z.B.
Speicher, ALU) zugreifen wollen und diese einen Mehrfachzugriff nicht unterstützt. In so einem Fall
muss der konfliktverursachende Befehl und alle nachfolgenden gesperrt werden bis die Ressource frei
ist (interlocking). Eine Verbesserung kann sein, solche Ressourcen, die häufig gebraucht werden,
doppelt zur Verfügung zu stellen oder diese Ressourcen selbst als Fließband zu organisieren.
Ein Datenflusskonflikt entsteht durch logische Abhängigkeiten zwischen Befehlen. Wenn ein
Befehl A ein Ergebnis aus einem anderen Befehl B als Operand benutzt können wie beim
Betriebsmittelkonflikt durch die Sperrung der nachfolgenden Befehle Wartezeiten entstehen, wenn der
Befehl A schon im Fließband ist, aber das Ergebnis des Befehls B in dieser Stufe noch nicht zur
Verfügung steht. Das Ergebnis eines Befehls wird normalerweise in einer der letzten Fließbandstufen
in den Registerspeicher geschrieben. Die Rechenoperation, die das Ergebnis liefert, wird aber oft
schon in einer früheren Stufe ausgeführt. Über einen Bypass kann dieses Ergebnis schon in einer
früheren Stufe für nachfolgende Berechnungen zur Verfügung gestellt werden (bypassing,
forwarding). Dadurch können Wartezeiten verkürzt werden.
Ein Kontrollflusskonflikt ist dann vorhanden, wenn sich ein Befehl im Fließband befindet, der
an dieser Stelle nicht ausgeführt werden soll. Ursache für diese Situation sind bedingte Sprungbefehle,
bei denen in der ersten Fließbandstufe noch nicht entschieden werden kann, ob ein Sprung ausgeführt
wird oder nicht. Werden die Befehle sequentiell abgearbeitet, kann es sein, dass alle dem
Sprungbefehl nachfolgenden Befehle, die sich schon im Fließband befinden, annulliert werden
müssen, wenn sich in einer späteren Stufe herausstellt, dass die Bedingung für einen Sprung erfüllt ist.
Bei allen Konflikten entsteht also eine Strafe (penalty) von einem bis mehreren Taktzyklen, in
denen der Prozessor untätig ist bzw. nicht erwünschte Befehle ausführt, die dann annulliert werden
müssen. Um den Befehlsdurchsatz zu erhöhen ist es also sinnvoll, diese Konflikte zu vermeiden.
Nachfolgend werden Methoden beschrieben, die gegenüber der sequentiellen Verarbeitung und
anschliessender Annullierung von Befehlen bei Kontrollflusskonflikten, erhebliche Verbesserungen
darstellen.
1.2. Kontrollflusskonflikte minimieren
Nach [1] gibt es im wesentlichen drei Möglichkeiten, die Annullierungen bei
Kontrollflusskonflikten, die in Verzögerungen resultieren, zu reduzieren. Die erste Möglichkeit besteht
darin, die Sprungbefehle im Programm einfach wegzulassen. Bei den unbedingten Sprüngen ist das
möglich, indem man die durch den Sprung aufgerufenen Programmteile in den aufrufenden Teil
integriert. Bei bedingten Sprüngen ist das so nicht möglich, da in vielen Fällen erst zur Laufzeit
entschieden werden kann, ob ein Sprung stattfindet oder nicht. Auf die Sprungbefehle kann aber
verzichtet werden, wenn man jedem einzelnen Befehl eine Bedingung zuordnet, unter der er
ausgeführt wird. Diese Bedingung kann auch leer sein, d.h. der Befehl wird immer ausgeführt. Diese
bedingte Befehlsausführung (predication, conditional execution) hat den Nachteil, dass in jedem
Befehl die Bedingung codiert sein muss.
1 In der Literatur sind für Betriebsmittelkonflikt auch die Begriffe Ressourcenkonflikt und Struktureller
Konflikt gebräuchlich. Anstatt Datenflusskonflikt wird auch Datenkonflikt verwendet und
Kontrollflusskonflikt wird auch Steuerungskonflikt oder Steuerflusskonflikt genannt.
1
Die zweite Möglichkeit ist die verzögerte Sprungtechnik (delayed branch). Dabei werden im
Fließband alle dem Sprung nachfolgenden Befehle korrekt ausgeführt und dann nach dieser
Verzögerung gesprungen. Das bedeutet für den Compiler, dass die Erzeugung des Maschinencodes
deutlich komplexer wird, da man Sprungbefehle vorziehen kann. In den Verzögerungsstufen (delay
slots) können nur solche Befehle platziert werden, die noch vor dem Sprung ausgeführt werden
können. Sind die Abstände (Anzahl der Befehle) zwischen den Sprungbefehlen gering, so lassen sich
bei Fließbändern mit vielen Stufen nicht alle Stufen sinnvoll füllen. Das Ergebnis ist dann nicht mehr
optimal. Der Vorteil dieser Methode ist die einfache Realisierbarkeit, da auf Annullierung verzichtet
werden kann.
Die dritte Möglichkeit, die im folgenden detailliert behandelt wird, ist die Sprungvorhersage
(branch prediction). Das Prinzip dabei ist, dass mit einer hohen Wahrscheinlichkeit schon in einer
frühen Stufe des Fließbands vorhergesagt wird, ob ein bedingter Sprung verzweigen wird oder nicht.
Nach dieser Vorhersage kann dann der nächste Befehl (entweder der sequentiell folgende oder der
Befehl an der Sprungadresse) im Fließband spekulativ verarbeitet werden und muss mit hoher
Wahrscheinlichkeit nicht annulliert werden. Es ist klar, dass weniger Annullierungen zu einem
höheren Befehlsdurchsatz führen. Bei Fließbändern mit vielen Stufen wird dies umso wichtiger, da
eine Annullierung alle einem Sprungbefehl nachfolgenden Befehle im Fließband betrifft.
Zur Verdeutlichung der Dimensionen, um die es hier geht, seien einige Zahlen genannt. In [2]
wird die Häufigkeit der Sprungbefehle mit 20 Prozent benannt. In [5] wird erwähnt, dass zwischen 15
und 30 Prozent aller Befehle Sprungbefehle sind. Dabei sind zwar die unbedingten Sprünge enthalten
und eine Reduzierung durch verbesserte Compiler wird möglich sein, dennoch ist es ein
bemerkenswerter statistischer Wert, der dafür spricht, dass die Sprungvorhersage ein wichtiges
Instrument sein kann. Wie wichtig, das sollen die folgenden Zahlen zeigen. Nach [6] würde eine
Verschlechterung der Rate der korrekt vorhergesagten Sprünge von 96 Prozent auf 93 Prozent bei
einer Fließbandarchitektur mit 20 Stufen (z.B. Pentium 4), bei der eine Fehlannahme eine Strafe von
bis zu 20 Takten verursachen kann, die Befehle pro Takt um 11 Prozent reduzieren. Eine gewaltige
Verschlechterung des Befehlsdurchsatzes. Es sollen nun verschiedene Methoden zu einer solchen
statistischen Vorhersage vorgestellt werden, deren Zuverlässigkeit unterschiedlich ist, aber bei einigen
durchaus in den Bereich von deutlich über 90 Prozent korrekter Vorhersagen kommt.
1.3. Statische Sprungvorhersage (static branch prediction)
Die Vorhersage bei einem Sprungbefehl kann zwei verschiedene Werte annehmen, der Befehl
wird verzweigen bzw. der Befehl wird nicht verzweigen. Im folgenden werden diese Vorhersagen mit
t (branch taken) und n (branch not taken) bezeichnet. Statisch bedeutet in diesem Fall, dass die
Vorhersage bei jedem Sprungbefehl dieselbe ist, d.h. entweder wird immer angenommen, dass der
Sprungbefehl verzweigt (predict taken) oder immer angenommen, dass der Sprungbefehl nicht
verzweigt (predict not taken). Im letzteren Fall gibt es bei allen Befehlen, die tatsächlich nicht
verzweigen, keine Verzögerung. Da aber, wie in [1] beschrieben, Sprungbefehle in nur einem Drittel
aller Fälle nicht verzweigen, ist die statische Vorhersage mit der Annahme t effizienter. In etwa zwei
Drittel der Fälle hätte man also eine korrekte Vorhersage. Diese Methode lässt sich dahingehend
optimieren, dass man nicht alle Sprungbefehle gleich behandelt. Für die unbedingten Sprungbefehle
muss die Vorhersage t gelten. Die Vorhersage t kann man auch für Sprungbefehle machen, die einen
Rückwärtssprung auslösen würden, weil man dies als einen Hinweis darauf verstehen kann, dass es
sich um eine Schleife handelt. Bei allen anderen Sprungbefehlen macht man die Annahme n.
Ein Problem bei dieser Technik besteht darin, dass bei der Annahme t eine Adressberechnung
notwendig ist. Wird diese Berechnung in der ersten Fließbandstufe durchgeführt, kann das Einfluss
auf die Taktlänge haben. Wird sie aus diesem Grund in der zweiten Stufe durchgeführt, verzögert sich
die Ausführung des Folgebefehls um einen Takt.
1.4. Dynamische Sprungvorhersage (dynamic branch prediction)
Bei der dynamischen Sprungvorhersage wird die Tatsache ausgenutzt, dass Sprungbefehle, die
2
in einem Programm mehrfach ausgeführt werden, bestimmte Muster auftreten. So lässt sich zum
Beispiel mit hoher Wahrscheinlichkeit korrekt vorraussagen, dass ein Sprungbefehl, der schon
mehrere Male in Folge verzweigt hat, wieder verzweigen wird. Umgekehrt ist das ebenfalls möglich.
Ein Sprungbefehl, der in vergangenen Aufrufen abwechselnd verzweigt und nicht verzweigt hat, wird
mit hoher Wahrscheinlichkeit dieses Muster beibehalten. Dies geht auf eine Untersuchung von Lee
und Smith zurück, die in [1] erwähnt wird. Demnach können über 90 Prozent der
Sprungentscheidungen richtig vorhergesagt werden, indem man die Historie der jeweiligen Befehle
betrachtet. Dafür ist es jedoch notwendig die Historie zu kennen, sie muss also gespeichert werden. Im
Sprungvorhersagecache (branch prediction cache) wird zu jeder Adresse eines Sprungbefehls die
jeweilige Historie gespeichert. Entsprechend des dort vorhandenen Eintrags kann nun eine Vorhersage
gemacht werden. Ist für einen Sprungbefehl keine Historie gespeichert (z.B. bei der ersten
Ausführung), muss zunächst eine statische Vorhersage gemacht werden. Nach der tatsächlichen
Entscheidung (nicht nach der Vorhersage) muss der Sprungvorhersagecache aktualisiert werden.
Die einfachste Realisierung dieser Technik ist die dynamische Sprungvorhersage mit
einstufiger Historie (one bit predictor). Dabei wird die Vorhersage nach dem letzten aufgezeichneten
Verhalten getroffen. Fand bei der letzten Ausführung eine Verzweigung statt, so wird die Vorhersage t
getroffen und umgekehrt. Dieses Vorgehen kann als Zustandsgraph dargestellt werden (Abbildung 1),
in dem die Ausgabe die Vorhersage darstellt und die Eingabe die vorher getroffenen Entscheidungen
sind. Findet eine Verzweigung statt (im Unterschied zur Vorhersage sei die tatsächliche Entscheidung
mit dem Großbuchstaben T bezeichnet) wird im Cache der Zustand 0 gespeichert, findet keine
Verzweigung statt (N) wird 1 gespeichert. Im Zustand 0 wird die Vorhersage n getroffen, im Zustand 1
die Vorhersage t. Nach der tatsächlichen Entscheidung wird dann der Cache aktualisiert.
N
T
1
0
t
n
N
T
Abbildung 1: Dynamische Sprungvorhersage mit einstufiger
Historie
Das eben beschriebene Verfahren ist allerdings nicht sehr zuverlässig, wenn Sprungfolgen
auftreten, die häufig wechseln, da bei einem stetigen Wechsel des Sprungverhaltens immer die falsche
Entscheidung vorhergesagt würde. Abhilfe schafft die die dynamische Sprungvorhersage mit
zweistufiger Historie (two bit predictor). Notwendig ist nun ein Cache, der zu jedem Sprungbefehl
vier Zustände speichern kann, also die letzten beiden Entscheidungen über Verzweigungen. In
Abbildung 2 ist der Zustandsgraph zu sehen, der diese Methode darstellt. Die Vorhersage
unterscheidet sich gegenüber der der einstufigen Historie insbesondere durch den Zustand 10. Obwohl
bei der letzten Ausführung nicht verzweigt wurde, wird der Sprung noch als verzweigend
N
T
11
10
t
t
N
T
N
T
01
00
t
n
N
T
Abbildung 2: Dynamische Sprungvorhersage
mit zweistufiger Historie
3
angenommen. Wurde bei den letzten beiden Sprüngen mindestens einmal verzweigt (Zustände 01, 10
und 11) so wird die Vorhersage t getroffen. Betrachtet man nun einige Beispielfolgen (Beispiel 1) für
dieses Verfahren, sieht man, dass es auch hier zu Fehlvorhersagen kommen kann. Diese Art der
Vorhersage ist also ebenfalls noch verbesserungswürdig.
Beispiel 1: Beispiele bei der dynamischen Sprungvorhersage mit zweistufiger Historie
a) TNNTNNTNN...
Nach der Folge TN befindet man sich im Zustand 10, vorhergesagt wird t, tatsächlich wird aber N auftreten.
Nach der Folge NN befindet man sich im Zustand 00, vorhergesagt wird n, tatsächlich wird aber T auftreten.
Nach der Folge NT befindet man sich im Zustand 01, vorhergesagt wird t, tatsächlich wird aber N auftreten.
Andere zweistufige Folgen treten nicht auf. Die Vorhersage ist also in 100 Prozent der Fälle falsch.
b) TNTNTNTNTN...
Nach der Folge TN befindet man sich im Zustand 10, vorhergesagt wird t, tatsächlich wird auch T auftreten.
Nach der Folge NT befindet man sich im Zustand 01, vorhergesagt wird t, tatsächlich wird aber N auftreten.
In 50 Prozent der Fälle ist die Vorhersage falsch. Gegenüber der Vorhersage mit einstufiger Historie eine
Verbesserung
c) NTTNTTNTT...
Nach der Folge TN befindet man sich im Zustand 10, vorhergesagt wird t, tatsächlich wird auch T auftreten.
Nach der Folge TT befindet man sich im Zustand 11, vorhergesagt wird t, tatsächlich wird aber N auftreten.
Nach der Folge NT befindet man sich im Zustand 01, vorhergesagt wird t, tatsächlich wird auch T auftreten.
In einem Drittel der Fälle ist die Vorhersage falsch.
Eine solche Verbesserung findet man in der dynamischen Sprungvorhersage mit
Sättigungszähler (two bit predictor with saturation counter). Dieses Verfahren ist in Abbildung 3 als
Zustandsgraph dargestellt. Die vier Zustände geben an, ob ein Sprung als
1.
2.
3.
4.
sicher verzweigend (st, strongly taken)
sicher nicht verzweigend (sn, strongly not taken)
eher verzweigend (wt, weakly taken) oder
eher nicht verzweigend (wn, weakly not taken)
vorausgesagt wird. Verzweigt ein Sprung mehrmals in Folge, so wird aus dem Zustand 11 die
Vorhersage t gemacht. Wenn nun einmal nicht verzweigt wird, ändert sich an der Vorhersage für die
nächste Ausführung noch nichts. Erst nach zwei Fehlannahmen wird die Vorhersage aus dem sicheren
Zustand geändert. Allerdings ist die Vorhersage abhängig vom Startzustand. Beispielsweise würde die
Sprungfolge NTNTNT aus dem Startzustand 10 zu 100 Prozent falsch vorhergesagt, aus dem
Startzustand 11 nur zu 50 Prozent.
N
T
10
11
t (st)
T
t (wt)
T
N
00
n (sn)
T
N
01
n (wn)
N
Abbildung 3: Dynamische Sprungvorhersage mit
Sättigungszähler
4
Eine weitere Modifizierung ist in Abbildung 4 dargestellt, die dynamische Sprungvorhersage
mit Hysteresemethode (two bit predictor with hysteresis scheme). Die Modifizierung besteht darin,
dass aus einem schwachen Zustand nach einer Fehlvorhersage nicht in den anderen schwachen
Zustand gewechselt wird, sondern in den sicheren. Die Sprungfolge mit abwechselnd ausgeführter
Verzweigung wird so in jedem Fall nur zu 50 Prozent falsch vorausgesagt (siehe Beispiel 2).
Insgesamt lässt sich statistisch mit zweistufiger Historie nach [1] in über 90 Prozent der Fälle eine
korrekte Vorhersage treffen. Dieses Verfahren ist mit dem entsprechenden Mehraufwand an Hardware
auf n Bit, also n-stufige Historien, erweiterbar.
N
T
10
11
t (st)
T
N
T
01
n (wn)
t (wt)
N
00
n (sn)
N
T
Abbildung 4: Dynamische Sprungvorhersage mit
Hysteresemethode
Beispiel 2: Beispiele bei der dynamischen Sprungvorhersage mit zweistufiger Historie und Hysteresemethode
a) TNNTNNTNN...
Nach der Folge TN befindet sich der Automat entweder im Zustand 10 oder 00. Es wird entweder t oder n
vorhergesagt. Danach wird nicht verzweigt, der Automat geht also in den Zustand 00 über und wird bei dieser
Folge den Zustand nur noch zu 01 und wieder zurück wechseln, also immer n vorhersagen. Das ist in einem
Drittel aller Fälle falsch.
b) TNTNTNTNTN...
Nach der Folge TN befindet sich der Automat entweder im Zustand 10 oder 00. Im Zustand 10 wird danach
immer t vorhergesagt (Wechsel zwischen 10 und 11), was zu 50 Prozent falsch ist. Im Zustand 00 wird
danach immer n vorhergesagt (Wechsel zwischen 01 und 00), was ebenfalls zu 50 Prozent falsch ist.
c) NTTNTTNTT...
Nach der Folge TN befindet sich der Automat entweder im Zustand 11 oder 01. Es wird entweder t oder n
vorhergesagt. Danach wird verzweigt, der Automat geht also in den Zustand 11 über und wird bei dieser
Folge den Zustand nur noch zu 10 und wieder zurück wechseln, also immer t vorhersagen. Das ist in einem
Drittel aller Fälle falsch.
1.5. Adaptive Sprungvorhersage (adaptive branch prediction)
Die Zuverlässigkeit der dynamischen Sprungvorhersage lässt sich noch steigern, indem man
nicht nur die einzelnen Sprungfolgen, sondern Sprungmuster berücksichtigt. Bei der adaptiven
Sprungvorhersage wird zu jedem Sprungbefehl ein solches Sprungmuster erstellt, indem die
vergangenen n Sprungentscheidungen aufgezeichnet werden und in einer Sprunghistorientabelle
(branch history table, BHT) gespeichert werden. Weiterhin gibt es eine Sprungmustertabelle (pattern
history table, PHT), in der zu jedem Sprungmuster der Länge n eine Vorhersage gespeichert ist. Diese
Vorhersage richtet sich normalerweise danach, wie in der Vergangenheit nach dem jeweiligen Muster
entschieden wurde und ist abhängig vom verwendeten Verfahren für die Vorhersage (z.B. dynamische
Sprungvorhersage mit Hysteresemethode). Sind sowohl die Sprungmustertabelle als auch die
5
Sprunghistorientabelle global, so werden auch miteinander korrelierende Sprungverhalten
verschiedener Sprungbefehle berücksichtigt (correlation based prediction).
In Abbildung 5 ist die grundsätzliche Funktionsweise der adaptiven Sprungvorhersage mit
lokalen Sprungmustertabellen und lokalen Sprunghistorientabellen dargestellt. Beim Einlesen des
Sprungbefehls wird in der BHT, die nach den Befehlsadressen organisiert ist, die Sprunghistorie
ausgelesen, in diesem Beispiel 4 Sprünge. Die dem jeweiligen Muster zugehörige Vorhersage wird aus
der lokalen PHT (in der BHT integriert) des Sprungbefehls gelesen und getroffen. Nach der
tatsächlichen Entscheidung, werden die Sprunghistorientabelle und je nach Sprungvorhersageautomat
die Sprungmustertabelle aktualisiert. Nach [1] lassen sich damit bis zu 97 Prozent aller Sprünge
korrekt vorhersagen. Allerdings benötigt diese Methode für jeden Sprungbefehl eine eigene
Sprungmustertabelle, was den Aufwand extrem hoch werden lässt. Eine weniger aufwändige Methode
ist die adaptive Sprungvorhersage mit globaler Sprungmustertabelle. Das Funktionsprinzip ist
identisch zu dem vorigen, nur dass zu jedem Sprungbefehl dieselbe (einzige) Sprungmustertabelle
zugeordnet wird. Auf diese Weise werden immer noch häufige Muster korrekt vorhergesagt und der
Aufwand ist deutlich geringer, jedoch ist diese Technik weniger zuverlässig, wenn verschiedene
Sprungbefehle auch verschiedene Sprungmuster aufweisen.
PHT ($0004)
BHT
Adresse
Sprungmuster
$0004
...
...
$50A4
...
NNNT + PHT($0004)
TTTN + PHT($50A4)
Sprungmuster
NNNN
NNNT
...
TTNT
TTTN
TTTT
Vorhersage
00 -> n
00 -> n
11 -> t
00 -> n
01 -> n
Sprungvorhersage (z.B.
dynamisch)
PHT ($50A4)
Sprungmuster
NNNN
NNNT
...
TTNT
TTTN
TTTT
Vorhersage
00 -> n
01 -> n
11 -> t
11 -> t
11 -> t
...
Abbildung 5: Adaptive Sprungvorhersage mit lokalen Sprungmustertabellen und lokalen
Sprunghistorientabellen
Noch eine weitere Möglichkeit ist es, alle Sprungbefehle und deren Folgen
zusammenzufassen. Es gibt dann nur eine globale Sprungmustertabelle und nur einen Eintrag in der
Sprunghistorientabelle, weshalb sie von einer Tabelle zu einem Register schrumpft (branch history
register, BHR). Die Vorgehensweise nennt sich globale adaptive Sprungvorhersage und ist ansonsten
identisch mit den beiden vorangegangenen. In Abbildung 6 ist eine schematische Darstellung dieser
Technik gegeben. Man spricht in dem Zusammenhang auch von (m,n)-Prädiktoren, wobei m die
Anzahl der Bits im BHR ist und n die Anzahl der Bits der Vorhersageeinheit. Benötigt werden dabei
2m Tabelleneinträge in der Sprungmustertabelle oder anders gesagt, 2m Vorhersageeinheiten. Die
lokale zweistufige dynamische Sprungvorhersage ist also ein (0,2)-Prädiktor. Die in der Abbildung
dargestellte globale Sprungvorhersage ist ein (4,2)-Prädiktor.
6
PHT
Sprungmuster
NNNN
NNNT
...
TTNT
TTTN
TTTT
BHR
NNNT
Vorhersage
00 -> n
00 -> n
Sprungvorhersage (z.B.
dynamisch)
11 -> t
00 -> n
01 -> n
Abbildung 6: Globale adaptive Sprungvorhersage, (4,2)-Prediktor.
Der Nachteil der globalen Methode ist, dass für die Vorhersage einer Sprungentscheidung oft
die Historie von anderen Sprungbefehlen herangezogen wird. Es ist leicht einzusehen, dass es dann zu
Fehlannahmen kommt. Von Pan, So und Rahmeh ist in [3] ein Vorschlag zur Verbesserung gemacht
worden. Bei der Indexselektion (index selection, gselect) wird die Sprungmustertabelle vom globalen
Modell ausgehend so erweitert, dass zu jedem Muster 2i Einträge existieren. Die ersten i Bits der
Adresse des Sprungbefehls legen dabei fest, nach welchem dieser Einträge die Vorhersage getroffen
werden soll (Abbildung 7a). Konflikte treten nun nur noch auf, wenn mehrere Sprungbefehle die
gleichen unteren i Bits in ihrer Adresse aufweisen. Nach [4] weist die Indexselektion eine ähnlich
hohe Zuverlässigkeit auf wie die lokale adaptive Sprungvorhersage (bei gleichem
Ressourcenaufwand). Eine weitere Modifikation ist die Indexteilung (index sharing, gshare). Dabei
werden die m Bits des BHR und die unteren m Bits der Sprungbefehlsadresse bitweise mit einem XOR
(exklusives oder) verknüpft. Mit dem so entstandenen Hashwert wird auf die Sprungmustertabelle
zugegriffen. Auf diese Weise werden bei gleichem Hardwareaufwand im Vergleich zur Indexselektion
mehr Adressbits (weniger aliasing) und mehr Sprunghistoriebits (genauere Vorhersage) verwendet.
Für die Darstellungen in Abbildung 7 heißt das, dass der Hardwareaufwand zur Speicherung der
Sprungmustertabelle gleich groß ist, wenn k = i + m. Daraus folgt, dass k >= i und k >= m ist.
BHR
Adresse
m Bits
BHR
i Bits
Adresse
k Bits
k Bits
XOR
i+m Bits
(a) gselect
(b) gshare
k Bits
PHT
Sprungmuster
i+m Bits
...
...
PHT
Vorhersage
00 -> n
...
Sprungmuster
k Bits
...
...
Vorhersage
00 -> n
...
Abbildung 7: Indexselektion (a) und Indexteilung (b)
1.6. Kombinierte und hierarchisch organisierte Sprungvorhersageverfahren
Die kombinierte Sprungvorhersage (hybrid branch prediction) bezeichnet die gleichzeitige
Verwendung zweier Vorhersageverfahren (z.B. ein lokales und ein globales). Der Grund, eine
Kombination als Lösung zu implementieren, ist, dass in allen Verfahren unterschiedliche
Sprungmuster gut bzw. schlecht vorhergesagt werden, so werden bei der globalen Vorhersage die
Korrelationen zwischen den Sprungbefehlen berücksichtigt, aber gleichzeitig das individuelle
Sprungverhalten vernachlässigt. Eine situationsabhängige Verwendung könnte also die
7
Zuverlässigkeit erhöhen. Beide verwendeten Vorhersagetechniken machen dabei gleichzeitig eine
Vorhersage. Ein zusätzliches Element, ein Auswahlbaustein (choice predictor), muss dann eines der
beiden Ergebnisse auswählen. Dabei kann er vorgehen wie ein dynamisches
Sprungvorhersageverfahren und bei Fehlannahmen das Verfahren wechseln (anstatt die Vorhersage
bei Fehlannahme zu wechseln).
Eine andere Art der Kombination von Vorhersageverfahren ist eine hierarchische Struktur.
Dabei wird die hohe Zuverlässigkeit von komplexen Vorhersageverfahren und die kurze Verzögerung
von einfacheren Verfahren kombiniert. Eine Methode ist die verfeinernde Sprungvorhersage
(overriding branch prediction). In der ersten Fließbandstufe wird eine Vorhersage von einem
einfachen Verfahren gemacht. Erst später, wenn aufgrund der ersten Vorhersage schon ein Folgebefehl
im Fließband ist, wird die komplexe Vorhersage gemacht. Sind die Vorhersagen unterschiedlich, so
werden die Folgebefehle annulliert und gemäß der komplexen Vorhersage fortgefahren. Stellt sich
dann heraus, dass die komplexe Vorhersage falsch war, müssen zum zweiten mal die Folgebefehle im
Fließband annulliert werden. Eine andere Methode ist die Verwendung von Caches. Ein
Vorhersagezustandscache wird verwendet, um Vorhersagen zu jedem Sprungbefehl zu speichern, die
dann sofort abrufbar sind. Sind in dem Cache keine Vorhersagen zu dem betreffenden Sprungbefehl
vorhanden, so wird eine einfache schnelle Vorhersage gemacht. Der Cache wird später nach der
tatsächlichen Sprungentscheidung durch eine komplexe Sprungvorhersageeinheit aktualisiert, so dass
bei der nächsten Ausführung die Vorhersage bereits getroffen wurde.
Zusammenfassend lässt sich sagen, dass jede der hier beschriebenen Vorhersageverfahren
Vor- und Nachteile hat. Welches davon (auch modifiziert oder kombiniert) zum Einsatz in
tatsächlichen Architekturen kommt, hängt von der Zuverlässigkeit, dem Hardwareaufwand und der
Strafe bei Fehlvorhersagen ab. Diese hängt wiederum von der Realisierung des Fließbandes und den
damit verbundenen Recheneinheiten und Caches ab.
8
2. Sprungzielvorhersage
Bei der bisherigen Betrachtung wurde eine Tatsache völlig außer Acht gelassen. Nämlich die,
dass die Sprungzieladresse bekannt sein muss, um den Befehl nach einem korrekt (oder auch nicht
korrekt) vorhergesagten Sprung in das Fließband zu laden. Die Adresse lässt sich aber normalerweise
erst in einer späteren Stufe berechnen. Um dieser Berechnung vorzugreifen und spekulativ (wie bei
der Sprungvorhersage) einen Befehl auszuführen, wird ein Sprungzielcache (branch target buffer2,
BTB) verwendet. In diesem Cache werden zu den Sprungbefehladressen die Zieladressen, auf die
verzweigt wurde, gespeichert. Wird der Sprung ein weiteres mal ausgeführt, kann ohne Verzögerung
das mögliche Sprungziel aus dem Cache geladen werden. Einige Sprungbefehle verzweigen allerdings
nicht immer auf das gleiche Ziel, sondern sind abhängig von anderen Werten in Registern oder
Speicherinhalten. Bei diesen Befehlen muss das berechnete Sprungziel mit dem spekulativen
verglichen werden. Stimmt es nicht überein, müssen alle nachfolgenden Befehle wieder aus dem
Fließband annulliert werden. Bei Sprungbefehlen, deren Zieladresse sich niemals ändert liefert diese
Methode eine perfekte Vorhersage. Allerdings kann es Sprungbefehle geben, die einmalig ihr
Sprungziel verändern und danach wieder auf das alte Sprungziel verweisen. Wegen solcher Fälle
wurde von Calder, Grunwald und Lindsay, wie in [1] beschrieben, vorgeschlagen, eine Gewichtung
der Eintragung im Sprungzielcache einzuführen. Wie bei der dynamischen Sprungvorhersage wird
hier die Vorhersage nur verändert (durch den neuen tatsächlich berechneten Wert ersetzt), wenn ein
Sättigungszähler einen bestimmten Wert erreicht hat. Dieser Zähler kann analog zum
Sprungvorhersageverfahren nach richtigen und falschen Vorhersagen erhöht bzw. verringert werden.
In dem eben beschriebenen Verfahren wird allerdings jeweils nur die Folge von einzelnen
Sprungzielen betrachtet. Auch hier kann man Verbesserungen der Zuverlässigkeit erreichen, wenn
man ein adaptives Verfahren anwendet, dass analog zum Sprungmuster beim
Sprungvorhersageverfahren einen Sprungpfad betrachtet. Im Sprungpfad (path history register, PHR)
sind die Zieladressen der vorher ausgeführten Sprünge gespeichert. In Abbildung 8 ist das Prinzip
eines globalen Verfahrens dargestellt. Analog zur Sprungmustertabelle aus den
Sprungvorhersageverfahren wird hier eine Pfadhistorientabelle verwendet, die zu jedem Muster eine
Sprungzieladresse zuordnet. In der Abbildung wird aus dem PHR die Historie von Zieladressen ZA1ZA2-ZA1-ZA2 gelesen. Dieser Folge wird in der Pfadhistorientabelle die Zieladresse ZA1
zugeordnet. Nach der Berechnung des tatsächlichen Sprungziels wird das PHR aktualisiert und
gegebenenfalls die Pfadhistorientabelle, wenn das Sprungziel von der Vorhersage abweicht.
Pfadhistorientabelle
Sprungmuster
PHR
ZA1 – ZA2 – ZA1 – ZA2
ZA1 – ZA2 – ZA1 – ZA2
ZA3 – ZA3 – ZA3 – ZA1
...
Vorhersage
ZA1
ZA3
...
Abbildung 8: Globale Sprungzielvorhersage
2 Anstelle von branch target buffer verwendet man auch die englischen Begriffe branch target cache oder
target instruction cache.
9
3. Wertvorhersage
Die Wertvorhersage ist ein Instrument, das es ermöglicht Ergebnisse von Berechnungen
vorherzusagen. Das ist interessant für Fälle, in denen im Fließband befindliche Befehle Operanden
benutzen, die von direkt vorangehenden Befehlen als Ergebnis berechnet werden. In solchen Fällen, in
denen diese Datenflusskonflikte nicht durch einen Bypass gelöst werden können (wie z.B. bei einem
Ladebefehl, der einen Wert aus dem Hauptspeicher lädt), kann durch die Vorhersage der
Speicheradresse schon vor dem eigentlichen Laden des Wertes der spekulative Wert an die
nachfolgenden Befehle weitergegeben werden. Auch Kontrollflusskonflikte können durch die
Wertvorhersage gelöst werden, nämlich indem man bei bedingten Sprüngen nicht mehr statistisch eine
Sprungentscheidung vorhersagt, sondern mit vorhergesagten Werten die Bedingung für einen Sprung
einfach ausrechnet. Da allerdings eine Wertvorhersage nicht an die Zuverlässigkeit von
Sprungvorhersageverfahren herankommt, kann diese Technik lediglich eine Erweiterung dieser
darstellen. Im den folgenden drei Abschnitten sollen Methoden zur Wertvorhersage vorgestellt
werden.
3.1. Konstante Wertvorhersage (last value prediction)
Hierbei wird in einer Wertvorhersagetabelle (value prediction table, VPT) zur jeweiligen
Befehlsadresse ein Wert gespeichert. Bei der ersten Ausführung dieses Befehls ist also noch kein Wert
gespeichert. Bei erneuter Ausführung kann jedoch schon dieser Wert ausgelesen und als spekulatives
Ergebnis benutzt werden. Stellt sich in der nachträglichen Überprüfung der Vorhersage heraus, dass
der Wert falsch war, müssen die nachfolgenden Befehle annulliert und erneut ausgeführt werden. Die
Strafe, die dabei verursacht wird, könnte sogar gegenüber der Verarbeitung gänzlich ohne Vorhersage
mehr Takte benötigen. Aus diesem Grund empfiehlt es sich auch bei dieser Technik mit einem
Sättigungszähler zu arbeiten (Abbildung 9). Analog zur dynamischen Sprungvorhersage kann durch
diesen Zähler festgelegt werden, ob es eine sichere Übereinstimmung gibt, eine nicht so sichere
Übereinstimmung, eine nicht so sichere Nichtübereinstimmung oder eine sichere
Nichtübereinstimmung. Der Unterschied besteht darin, dass hier nicht zwischen t (branch taken) und n
(branch not taken) unterschieden wird, sondern darüber, ob der Wert überhaupt als Vorhersage
genommen wird. Desweiteren kann der Zustand des Sättigungszählers zur Entscheidung darüber
herangezogen werden, ob ein falsch vorhergesagter Wert in der VPT durch den neuen berechneten
Wert ersetzt werden soll. Z.B. ist das dann sinnvoll, wenn der Zähler sich in dem Zustand einer
sicheren Nichtübereinstimmung befindet. Zu erwähnen ist dabei noch die 2-Delta Methode, nach der
ein neuer Wert nur in die VPT geschrieben wird, nachdem er mindestens zweimal in Folge auftrat,
was wiederum die Speicherung des letzten tatsächlichen Wertes zu jedem Befehl erfordert. Eine noch
etwas aufwändigere Methode ist es, zu jedem Befehl gleich mehrere Werte zu speichern und alle mit
einem Zähler zu versehen. Die Vorhersage wird dann dem Wert entsprechen, der den höchsten
Zählerstand hat, sofern er nach dem Sättigungsprinzip überhaupt als sichere Vorhersage gelten kann.
F
K
10
11
gültig
K
gültig
F
K
F
00
nicht gültig
K
F = Falsche Vorhersage
K = Korrekte Vorhersage
01
nicht gültig
F
Abbildung 9: Sättigungszähler für die konstante Wertvorhersage
10
3.2. Differentielle Wertvorhersage (stride prediction)
Diese Art der Vorhersage eignet sich für konstant auftretende Werte, sowie für Werte, die mit
jeder Ausführung schrittweise erhöht bzw. reduziert werden. Gespeichert wird dabei der letzte
berechnete Wert und eine Schrittweite (die bei konstanten Werten 0 ist), aus denen sich dann die
Vorhersage generieren lässt. Wie bei der konstanten Wertvorhersage, können hier ebenfalls
Sättigungszähler und das 2-Delta-Verfahren angewendet werden, um Vorhersagen zuzulassen bzw.
Einträge in der VPT zu ersetzen. In Abbildung 10 ist eine schematische Darstellung der VPT gegeben.
Die Spalte Delta-2-Wert ist optional. Gegenüber der konstanten Wertvorhersage ist nur die Spalte
Schrittweite hinzugekommen.
VPT
Adresse
Vorhersagewert
2-Delta-Wert (jüngster Wert)
$00E4
...
...
$50A4
...
$0FF4
$0FF0
$3FA7
$82BC
Schrittweite
$0004
...
...
$00FF
...
Sättigungszähler
11 -> gültig
00 -> nicht gültig
Abbildung 10: Wertvorhersagetabelle bei differentieller Vorhersage
3.3. Kontextbasierte Wertvorhersage (context based prediction)
Die aufwändigste der drei hier beschriebenen Wertvorhersagemethoden ist die kontextbasierte
Wertvorhersage. Sie funktioniert nach dem gleichen Prinzip wie die adaptive Sprungvorhersage. Zu
jedem wertegenerierenden Befehl wird eine Wertehistorie in einer Wertehistorientabelle (value
history table, VHT) gespeichert (vgl. BHT aus 1.5). In der VPT sind jeder dieser Historien ein
Vorhersagewert (der sich nach den vergangenen Fortsetzungen nach der jeweiligen Wertefolge richtet)
und Sättigungszähler zugeordnet (vgl. PHT aus 1.5). Nach Feststellung eines tatsächlichen Wertes
werden VHT und VPT aktualisiert. Der wesentliche Unterschied zur adaptiven Sprungvorhersage liegt
im Aufwand der Realisierung. Während bei der Sprungvorhersage nur zwei unterschiedliche
Vorhersagen getroffen werden können, und damit eine n lange Historie höchstens 2n verschiedene
Formen annehmen kann, so sind dies bei der Wertvorhersage fast unbegrenzt viele. Das ist natürlich
nicht realisierbar, so dass Aliasing ein Problem darstellt (siehe Abschnitt 1.5). Der Trade-Off von
Zuverlässigkeit und Hardwareaufwand ist in dem Fall so groß, dass kombinierte Lösungen wie bei der
Sprungvorhersage auch bei der Wertvorhersage ein besseres Ergebnis liefern als die einzelnen
Methoden für sich genommen.
3.4. Wertvorhersage als Instrument für Sprungvorhersage
Wie bereits erwähnt, kann die Wertvorhersage als Ergänzung zu einem der
Sprungvorhersageverfahren aus Abschnitt 1 verwendet werden. Da nach [1] die Zuverlässigkeit der
Wertvorhersage bei höchstens 78 Prozent korrekter Vorhersagen liegt, kann es die anderen
Sprungvorhersageverfahren nicht komplett ersetzen, ist jedoch bei bestimmten Sprungentscheidungen
zuverlässiger. Deshalb scheint es am effizientesten, ein herkömmliches Verfahren mit dem Verfahren
der Wertvorhersage zu kombinieren. Dabei werden beide Verfahren gleichzeitig eine Vorhersage
treffen und ein weiterer Baustein wird dann eines der beiden Ergebnisse nach einem bestimmten
Verfahren auswählen (vgl. choice predictor aus Abschnitt 1.6).
11
4. Literatur- und Abbildungsverzeichnis
4.1. Literatur
[1] M. Menge, Moderne Prozessorarchitekturen. Springer, Berlin 2005
[2] C. Siemers, M. Eckert, A. Lauchner, tecChannel-Compact Prozessor-Technologie. IDG Interactive
GmbH, München 2004
[3] S.-T. Pan, K. So, J. T. Rahmeh, Improving the Accuracy of Dynamic Branch Prediction Using
Branch Correlation. S. 76-84, ASPLOS, 1992
[4] S. McFarling. Combining Branch Predictors. Technical Note TN-36, Digital Western Research
Laboratory, 1993
[5] R. G. Wedig, M. A. Rose, The Reduction of Branch Instruction Execution Overhead Using
Structured Control Flow. S. 119-125, ISCA, 1984
[6] D. A. Jiménez, Delay-Sensitive Branch Predictors for Future Technologies. University of Texas,
Austin, 2002
4.2. Abbildungen
Abbildung 1: Dynamische Sprungvorhersage mit einstufiger Historie
Abbildung 2: Dynamische Sprungvorhersage mit zweistufiger Historie
Abbildung 3: Dynamische Sprungvorhersage mit Sättigungszähler
Abbildung 4: Dynamische Sprungvorhersage mit Hysteresemethode
Abbildung 5: Adaptive Sprungvorhersage mit lokalen Sprungmustertabellen und lokalen
Sprunghistorientabellen
Abbildung 6: Globale adaptive Sprungvorhersage, (4,2)-Prediktor
Abbildung 7: Indexselektion (a) und Indexteilung (b)
Abbildung 8: Globale Sprungzielvorhersage
Abbildung 9: Sättigungszähler für die konstante Wertvorhersage
Abbildung 10: Wertvorhersagetabelle bei differentieller Vorhersage
4.3. Beispiele
Beispiel 1: Beispiele bei der dynamischen Sprungvorhersage mit zweistufiger Historie
Beispiel 2: Beispiele bei der dynamischen Sprungvorhersage mit zweistufiger Historie und
Hysteresemethode
12

Documents pareils