σμ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 AcademyFeuilles de routeParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Feuilles de routeParcours
AO
+1,2 k apprenants
Connexion
  • 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 AcademyFeuilles de routeParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Feuilles de routeParcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Cache locality›Module 1 · Les caches de zéro›Sujet 1.4·~45 minIntermédiaire

Localité temporelle et ensembles de travail

Position dans le parcoursModule 1 sur 3 · Sujet 4 sur 4
1.4 Localité temporelle et ensembles de travail
—Score du lab— / 100XP total—Série—

5 min de lecture4 exemples de code

  1. 01Relire la même ligne
  2. 02Des distances aux taux de succès
  3. 03Ensembles de travail et la falaise
  4. 04Une moyenne glissante sur de vrais prix
  5. 05Ce que vous allez construire

Un cache n'aide que pour les données que vous relisez, et ce qui compte est le délai. Ce cours mesure cela avec un seul nombre, la distance de réutilisation, et s'en sert pour prédire d'un coup le taux de succès de toutes les tailles de cache, y compris la falaise où une boucle est juste un peu trop grande pour tenir.

01

Relire la même ligne

Les deux derniers sujets portaient sur l'endroit où vont les lignes. Celui-ci porte sur le moment où elles reviennent. Un programme qui lit un prix, travaille un peu, puis relit le même prix un instant plus tard montre de la localité temporelle. Plus l'écart est court, plus la ligne a de chances d'être encore dans le cache. Pensez aux livres sur votre bureau : celui que vous avez utilisé il y a une minute y est encore, celui d'il y a un mois est retourné sur l'étagère.

DéfinitionDistance de réutilisation

Pour une lecture d'une ligne, le nombre d'autres lignes différentes lues depuis la lecture précédente de cette même ligne. La première lecture d'une ligne n'a pas de distance.

Lire la ligne 5 deux fois de suite donne une distance de 0. Dans la séquence 1, 2, 3, 1, la dernière lecture a une distance de 2, car les lignes 2 et 3 sont venues entre-temps. Lire dix fois la ligne 2 entre deux lectures de la ligne 1 compte quand même pour une seule ligne. Le code garde une liste des lignes dans l'ordre de leur dernier usage, la plus récente en dernier. Quand une ligne revient, les lignes qui la suivent dans la liste sont exactement celles utilisées depuis.

main.pyPython
def reuse_distances(lines):    stack = []    out = []    for line in lines:        if line in stack:            position = stack.index(line)            out.append(len(stack) - 1 - position)1            stack.pop(position)        else:            out.append(None)        stack.append(line)    return outprint(reuse_distances([1, 2, 3, 1, 2, 1, 1]))
[None, None, None, 2, 2, 1, 0]
  1. 1Les lignes qui suivent celle-ci dans la liste sont exactement les lignes utilisées depuis sa dernière lecture : leur nombre est la distance.
02

Des distances aux taux de succès

Voici le fait utile. Prenez un cache qui contient C lignes et évince la moins récemment utilisée, quels que soient les numéros de ligne. À tout moment il contient les C lignes différentes utilisées le plus récemment. Une lecture réussit exactement quand sa ligne en fait partie, c'est-à-dire quand moins de C lignes différentes ont été lues depuis son dernier usage. Autrement dit, la lecture réussit quand sa distance de réutilisation est inférieure à C.

hit ⇔ reuse distance < capacity(1)pour un cache LRU entièrement flexible : toute ligne peut aller n'importe où, seul compte donc le nombre de lignes

Le code ci-dessous vérifie l'affirmation. Il simule un cache LRU pour des capacités de 1 à 4 et calcule aussi le taux de succès à partir des seules distances, sans aucun cache. Les deux colonnes concordent. Les distances sont calculées une fois, puis elles donnent le taux de succès de chaque taille de cache.

main.pyPython
def lru_hit_rate(lines, capacity):    cache = []    hits = 0    for line in lines:        if line in cache:            hits += 1            cache.remove(line)        elif len(cache) >= capacity:            cache.pop(0)        cache.append(line)    return hits / len(lines)def hit_rate_from_distances(distances, capacity):    hits = sum(1 for d in distances if d is not None and d < capacity)    return hits / len(distances)lines = [1, 2, 3, 1, 2, 3, 4, 1, 2, 3]d = reuse_distances(lines)for capacity in (1, 2, 3, 4):    print(capacity, "lines:", round(lru_hit_rate(lines, capacity), 3), round(hit_rate_from_distances(d, capacity), 3))1
1 lines: 0.0 0.0
2 lines: 0.0 0.0
3 lines: 0.3 0.3
4 lines: 0.6 0.6
  1. 1Les mêmes nombres dans les deux colonnes : les distances seules prédisent le taux de succès de chaque taille de cache.
Un seul passage donne toutes les tailles de cache

Sans distances, il faudrait relancer un simulateur pour chaque taille à tester. Avec elles, un seul passage sur la trace donne toute la courbe du taux de succès selon la taille du cache. Les ingénieurs de performance l'appellent la courbe de taux de défauts.

03

Ensembles de travail et la falaise

L'ensemble de travail d'une série de lectures est l'ensemble des lignes différentes qu'elles touchent. S'il tient dans le cache, le programme tourne presque entièrement depuis le cache. S'il est à peine plus grand, LRU peut échouer complètement. Prenez une boucle qui lit 48 lignes dans l'ordre, trois fois. Chaque ligne est relue après 47 autres, donc toutes les distances de réutilisation valent 47. Un cache de 47 lignes ou moins ne réussit donc jamais, et un cache de 48 réussit à chaque lecture après le premier passage.

main.pyPython
def sweep_lines(n_lines, passes):    return list(range(n_lines)) * passeslines = sweep_lines(48, 3)for capacity in (16, 32, 47, 48):    print(capacity, "lines:", round(lru_hit_rate(lines, capacity), 3))
16 lines: 0.0
32 lines: 0.0
47 lines: 0.0
48 lines: 0.667
Une ligne de trop petit peut signifier zéro succès

Le taux de succès ne baisse pas progressivement quand une boucle dépasse le cache. Avec LRU et une boucle qui parcourt les mêmes lignes dans le même ordre, il passe de 0,667 à 0,0 à la ligne exacte où l'ensemble de travail cesse de tenir. Un programme peut être rapide pour une taille d'entrée et plusieurs fois plus lent pour une taille un peu plus grande.

04

Une moyenne glissante sur de vrais prix

Une moyenne glissante calculée à la dure lit les 20 dernières valeurs chaque jour : elle relit 19 des 20 valeurs lues la veille. C'est un programme à forte localité temporelle. Le code construit les adresses lues pour les 600 premières clôtures, les transforme en lignes et mesure les distances, le taux de succès pour quatre tailles de cache et l'ensemble de travail de 20 lectures consécutives.

main.pyPython
def rolling_mean_trace(n, window, elem_bytes):    trace = []    for end in range(window - 1, n):        for position in range(end - window + 1, end + 1):            trace.append(position * elem_bytes)    return tracedef working_set(lines, window):    return max(len(set(lines[i:i + window])) for i in range(len(lines) - window + 1))lines = [address // 64 for address in rolling_mean_trace(600, 20, 8)]d = reuse_distances(lines)print(len(lines), "reads from", len(set(lines)), "lines")for capacity in (1, 2, 4, 8):    print(capacity, "lines:", round(hit_rate_from_distances(d, capacity), 3))print("working set of 20 reads:", working_set(lines, 20), "lines")
11620 reads from 75 lines
1 lines: 0.831
2 lines: 0.831
4 lines: 0.994
8 lines: 0.994
working set of 20 reads: 4 lines

Une ligne suffit pour 83 % des lectures, car la valeur suivante du tableau est dans la ligne qu'on vient de lire. Quatre lignes atteignent 99,4 %. Les 75 lignes de l'ensemble de données n'ont jamais à tenir : l'ensemble de travail de 20 lectures n'est que de 4 lignes, un minuscule cache suffit donc. C'est la différence entre la taille des données et la taille de l'ensemble de travail.

Ce que disent les vraies donnéesMoyenne glissante sur 20 jours des 600 premières clôtures de SPY
Lectures11,620depuis 75 lignes différentes
Ensemble de travail de 20 lectures4linestout l'ensemble de données n'a jamais à tenir
Taille de cache pour 90 % de succès3lines192 octets de cache
Parcours de 48 lignes, cache de 32 lignes0.0hitsavec 48 lignes : 0,667
Taux de succès de la moyenne glissante selon la taille du cache, en %
1 ligne83.1
2 lignes83.1
4 lignes99.4
8 lignes99.4
05

Ce que vous allez construire

Le labo demande les éléments ci-dessus, plus l'aide qui trouve le plus petit cache pour un taux de succès donné, et se termine par l'étude sur les vraies clôtures de SPY.

  • Fonction · questionS'appuie sur
  • reuse_distances(lines)Dans combien de temps chaque ligne est-elle relue ?Une liste en ordre de dernier usage
  • lru_hit_rate(lines, capacity)Que réussit un cache LRU simulé ?Des lignes en ordre LRU
  • hit_rate_from_distances(distances, capacity)Le même taux de succès, sans cache ?reuse_distances
  • working_set(lines, window)Combien de lignes touche une série de lectures ?Une fenêtre glissante
  • capacity_for(lines, target)Quelle taille minimale pour le cache ?reuse_distanceshit_rate_from_distances
  • rolling_mean_trace(n, window, elem_bytes)Quelles adresses lit une moyenne glissante lente ?De l'arithmétique simple
  • study(bars)Quelle est la localité d'une moyenne glissante sur les clôtures de SPY ?rolling_mean_tracecapacity_for

À retenir

  • La distance de réutilisation prédit les succès. Un cache LRU de C lignes réussit exactement les lectures dont la distance est inférieure à C : un passage de distances donne le taux de succès de chaque taille.
  • L'ensemble de travail fixe la taille. Ce qui doit tenir est l'ensemble de travail d'une série de lectures, pas toutes les données : 4 lignes suffisaient pour une table de 75 lignes.
  • Méfiez-vous de la falaise. Une boucle dont l'ensemble de travail dépasse d'une ligne un cache LRU peut perdre tous ses succès ; mesurez aux tailles où vous allez tourner.
Vérification rapide
Les lectures sont les lignes A, B, C, A. Quelle est la distance de réutilisation du dernier A ?
Choisissez une réponse.

Sujet suivant : vous savez maintenant comment une disposition devient une trace et une trace des succès et des défauts. Dans Tableau de structures contre structure de tableaux, vous vous en servez pour choisir comment disposer une table de ticks, en comparant les lectures de colonnes et de lignes entières dans les deux dispositions.

Lab : ce qui est noté

7 tâches · 100 pts
  • Distances de réutilisation20 pts
  • Un cache LRU simulé15 pts
  • Le taux de succès à partir des distances10 pts
  • L'ensemble de travail d'une fenêtre15 pts
  • Le plus petit cache10 pts
  • Une moyenne glissante lente10 pts
  • L'étude sur la table SPY20 pts
Explorateur · lab-cl-4
▾ lab-cl-4
▾ data
…
bash · dans le navigateur
learner@quantcraft:~/lab-cl-4$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-cl-4 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes