σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRoadmapsSkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
RoadmapsSkills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRoadmapsSkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
RoadmapsSkills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Cache locality-Skill›Modul 3 · Die ganze Maschine›Thema 3.6·~55 Min.Fortgeschritten

Sprungvorhersage

Position in der SkillModul 3 von 3 · Thema 6 von 7
3.6 Sprungvorhersage
—Lab-Punkte— / 100XP gesamt—Serie—

5 Min. Lesezeit3 Codebeispiele

  1. 01Warum der Prozessor rät
  2. 02Prädiktoren mit Gedächtnis
  3. 03Was ein Fehler kostet und warum Sortieren hilft
  4. 04Was Sie bauen werden

Ein Prozessor wartet nicht ab, wohin ein if geht: Er rät und fängt an zu arbeiten. Ein richtiger Tipp ist gratis, ein falscher wirft die Arbeit weg, etwa 15 Takte verloren. Wie oft er richtig rät, hängt von den Daten ab: Dieselbe Schleife über dieselben SPY-Renditen kostet 8,3-mal weniger Takte, sobald die Renditen sortiert sind.

01

Warum der Prozessor rät

Ein Prozessor arbeitet wie ein Fließband: Während eine Anweisung läuft, werden die nächsten schon geholt und dekodiert. Ein if unterbricht das Band, denn die nächste Anweisung hängt von seiner Antwort ab, die noch nicht fertig ist. Also macht der Prozessor eine Sprungvorhersage und läuft darauf voraus. Stimmt sie, geht nichts verloren. Stimmt sie nicht, wird die Arbeit auf dem falschen Pfad weggeworfen und das Band startet neu, was auf einem modernen Kern etwa 15 Takte kostet, so viel wie ein Besuch im L2-Cache. Wir schreiben das Ergebnis eines Sprungs als True, wenn er genommen wird. In einer Trading-Schleife ist ein Sprung etwa if daily_return > 0, und der Strom seiner Ergebnisse ist einfach ein True oder False pro Tag.

main.pyPython
def taken_sequence(values, threshold):    return [bool(value > threshold) for value in values]def always_taken_mispredicts(outcomes):    return sum(1 for outcome in outcomes if not outcome)returns = [0.004, -0.012, 0.007, 0.001, -0.003, 0.009]outcomes = taken_sequence(returns, 0)print(outcomes)print(always_taken_mispredicts(outcomes), "misses out of", len(outcomes))
[True, False, True, True, False, True]
2 misses out of 6

Von sechs Tagen hatten vier eine positive Rendite, der Sprung wird also viermal genommen und zweimal nicht. Der einfachste Prädiktor, immer genommen, liegt genau bei den zwei False-Ergebnissen falsch. Er liegt so oft richtig, wie der Sprung genommen wird, und ignoriert die Vorgeschichte.

02

Prädiktoren mit Gedächtnis

Echte Prozessoren nutzen die Vorgeschichte. Der 1-Bit-Prädiktor merkt sich, was der Sprung zuletzt getan hat, und rät dasselbe. Er ist gut, wenn die Ergebnisse in Serien kommen, zahlt aber für jedes Ausreißer-Ergebnis doppelt: einmal beim Auftreten und einmal, wenn die Serie weitergeht. Der 2-Bit-Prädiktor behebt das mit einem Zähler von 0 bis 3, der an beiden Enden stehen bleibt. Er rät „genommen“ bei 2 und 3, macht einen Schritt zu jedem Ergebnis und braucht daher zwei Ergebnisse in Folge gegen seinen Tipp, um umzudenken. Wir starten den 1-Bit-Tipp bei „nicht genommen“ und den Zähler bei 1.

main.pyPython
def one_bit_mispredicts(outcomes):    guess = False    wrong = 0    for outcome in outcomes:        if guess != outcome:            wrong += 1        guess = outcome    return wrongdef two_bit_mispredicts(outcomes):    counter = 1    wrong = 0    for outcome in outcomes:        if (counter >= 2) != outcome:            wrong += 1        counter = min(3, counter + 1) if outcome else max(0, counter - 1)1    return wrongruns = [True] * 4 + [False] * 4 + [True] * 4stray = [True] * 6 + [False] + [True] * 6for name, stream in (("runs", runs), ("one stray", stray)):    print(name, "| 1-bit", one_bit_mispredicts(stream), "| 2-bit", two_bit_mispredicts(stream))
runs | 1-bit 3 | 2-bit 5
one stray | 1-bit 3 | 2-bit 2
  1. 1Der Zähler macht einen Schritt zum Ergebnis und bleibt bei 0 und 3 stehen: Das macht ihn sättigend.

Bei den Vierer-Serien liegen beide Prädiktoren dreimal falsch (der erste Tipp und die zwei Wechsel). Bei einem einzelnen False zwischen genommenen Ergebnissen liegt der 1-Bit-Prädiktor dreimal falsch und der 2-Bit-Prädiktor nur einmal, weil der Zähler von 3 auf 2 fällt und weiter „genommen“ rät. Deshalb bevorzugen echte Prozessoren Zähler. Behalten Sie die andere Seite im Kopf: Haben die Ergebnisse kein Muster, kann kein Prädiktor besser sein als das Raten der häufigeren Antwort.

Bei der Vorhersage geht es um die Daten, nicht um den Code

Dasselbe if ist bei vorhersagbaren Daten billig und bei zufälligen teuer. Schreiben Sie einen Sprung nicht um, damit er „schneller“ wird, bevor Sie wissen, wie seine Ergebnisse in den echten Daten aussehen; messen Sie zuerst die Fehlvorhersagen.

03

Was ein Fehler kostet und warum Sortieren hilft

Um Fehler in Zeit umzurechnen, addieren wir sie: Jeder Sprung kostet einen Basistakt, und jeder Fehler addiert eine Strafe von 15. Nun das Experiment, nach dem diese Lektion benannt ist: Nehmen Sie die ersten 4.000 täglichen SPY-Renditen und führen Sie den Sprung return > 0 zweimal aus, über die Renditen in Datumsreihenfolge und über dieselben Renditen sortiert. Das Sortieren ändert nichts an den Zahlen, nur an ihrer Reihenfolge, aber es verwandelt die Ergebnisse von einem Münzwurf in zwei lange Serien: erst alle False, dann alle True.

main.pyPython
def cycles(n_branches, mispredicts, penalty=PENALTY, base=BASE_CYCLES):    return base * n_branches + penalty * mispredictsdef sorted_stream(values, threshold):    return taken_sequence(sorted(values), threshold)returns = [float(r) for r in load_bars()["close"].pct_change().dropna()][:4000]for name, stream in (("unsorted", taken_sequence(returns, 0)), ("sorted", sorted_stream(returns, 0))):    wrong = two_bit_mispredicts(stream)    print(name, "| always", always_taken_mispredicts(stream), "| 1-bit", one_bit_mispredicts(stream), "| 2-bit", wrong, "|", cycles(len(stream), wrong), "cycles")
unsorted | always 1800 | 1-bit 2035 | 2-bit 1950 | 33250 cycles
sorted | always 1800 | 1-bit 1 | 2-bit 2 | 4030 cycles

In Datumsreihenfolge sind 2.200 der 4.000 Renditen positiv, der Sprung wird also zu 55 % genommen und wechselt fast ohne Muster zwischen den Antworten: Immer-genommen liegt 1.800-mal falsch, der 1-Bit-Prädiktor 2.035-mal und der 2-Bit-Prädiktor 1.950-mal. Die Prädiktoren mit Gedächtnis sind sogar schlechter als der einfache Tipp, weil sie jedem Wechsel folgen. Sortiert sind die Ergebnisse 1.800 False gefolgt von 2.200 True, und der 2-Bit-Prädiktor liegt nur 2-mal falsch. Die Kosten fallen von 33.250 auf 4.030 Takte, 8,3-mal weniger, mit denselben Daten und derselben Schleife.

DefinitionFehlvorhersage-Strafe

Die Takte, die verloren gehen, wenn der Prozessor einen Sprung falsch vorhergesagt hat: Er verwirft die Arbeit auf dem falschen Pfad und füllt das Band neu, etwa 15 Takte auf einem modernen Kern.

Derselbe Trick in NumPy und C++

Ein vektorisierter Vergleich wie returns > 0 hat keinen Sprung pro Element und leidet darunter gar nicht. In C++ ist eine Schleife mit einem if über zufällige Daten der klassische Fall, in dem das vorherige Sortieren der Daten oder das Schreiben der Bedingung als Arithmetik sie um ein Mehrfaches schneller macht.

Was die echten Daten sagen4.000 tägliche SPY-Renditen, Sprung return > 0, Strafe 15 Takte
Immer genommen, Datumsreihenfolge1,800Fehler von 4.000
2 Bit, Datumsreihenfolge1,950Fehler, schlechter als immer genommen
2 Bit, sortiert2Fehler: eine Serie, dann die andere
Gewinn durch Sortieren8.3×weniger Takte (33.250 → 4.030)
Takte des 2-Bit-Prädiktors
Datumsreihenfolge33250
Sortiert4030
04

Was Sie bauen werden

Das Labor folgt der Lektion: die Ergebnisse eines Sprungs, die drei Prädiktoren, die Kosten in Takten, der sortierte Strom und eine Studie der SPY-Renditen in Datumsreihenfolge und sortiert.

  • Funktion · FrageBaut auf
  • taken_sequence(values, threshold)Was tut der Sprung bei jedem Wert?Einfache Arithmetik
  • always_taken_mispredicts(outcomes)Wie oft liegt „immer genommen“ falsch?Einfache Arithmetik
  • one_bit_mispredicts(outcomes)Und ein Prädiktor, der sich das letzte Ergebnis merkt?Einfache Arithmetik
  • two_bit_mispredicts(outcomes)Und ein sättigender Zähler?Einfache Arithmetik
  • cycles(n_branches, mispredicts)Was kostet das alles?Einfache Arithmetik
  • sorted_stream(values, threshold)Und wenn die Werte zuerst sortiert würden?taken_sequence
  • study(bars)Was spart das Sortieren bei SPY?sorted_streamtwo_bit_mispredictscycles

Das Wichtigste

  • Der Prozessor rät jedes `if`. Ein richtiger Tipp ist gratis, ein falscher kostet etwa 15 Takte, und ein Prädiktor mit Gedächtnis schlägt den einfachen Tipp nur, wenn die Ergebnisse in Serien kommen.
  • Ein Zähler schlägt ein einzelnes Bit. Der 2-Bit-Zähler ignoriert ein einzelnes Ausreißer-Ergebnis, wo der 1-Bit-Prädiktor doppelt zahlt.
  • Die Reihenfolge ändert die Kosten. Dieselben 4.000 Renditen kosten 33.250 Takte in Datumsreihenfolge und 4.030 sortiert, denn Sortieren verwandelt einen Münzwurf in zwei Serien.
Schnelltest
Ein Sprung hat die Ergebnisse True ×4, False ×4, True ×4. Der 1-Bit-Prädiktor startet bei „nicht genommen“. Wie oft liegt er falsch?
Wähle eine Antwort.

Nächstes Thema: Das Abschlussprojekt führt die ganze Fähigkeit zusammen. Sie erhalten eine Tick-Tabelle und eine Last, die sie liest, ordnen sie in Zeilen, Spalten oder Blöcken neu an, zählen die Cache-Fehlzugriffe jeder Anordnung mit dem selbst gebauten Cache, bewerten sie mit dem Latenzmodell des ersten Themas und beweisen, welche Anordnung gewinnt.

Lab: Was bewertet wird

7 Aufgaben · 100 Pkt.
  • Sprung-Ergebnisse5 Pkt.
  • Immer genommen10 Pkt.
  • Ein 1-Bit-Prädiktor15 Pkt.
  • Ein sättigender 2-Bit-Zähler20 Pkt.
  • Die Kosten in Takten10 Pkt.
  • Sortierte Werte10 Pkt.
  • Die Studie mit der SPY-Tabelle30 Pkt.
Explorer · lab-cl-12
▾ lab-cl-12
▾ data
…
bash · im Browser
learner@quantcraft:~/lab-cl-12$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-cl-12 wird auf die Startdateien zurückgesetzt und das Terminal geleert. Ihre aktuelle Lösung geht verloren – das lässt sich nicht rückgängig machen.

Wird zurückgesetzt
  • main.py → Startcode
  • Terminal-Verlauf und Testausgabe
  • Nicht eingereichte Änderungen
Bleibt erhalten
  • Beste Lab-Punktzahl
  • Ihre XP und Ihre Serie
  • Vorlesungsfortschritt und Notizen