σμ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 3 · La machine au sens large›Sujet 3.2·~50 minAvancé

TLB et grandes pages

Position dans le parcoursModule 3 sur 3 · Sujet 2 sur 7
3.2 TLB et grandes pages
—Score du lab— / 100XP total—Série—

5 min de lecture3 exemples de code

  1. 01Deux sortes d'adresses
  2. 02Un cache de traductions
  3. 03Lire des enregistrements au hasard
  4. 04Ce que vous allez construire

Avant qu'une lecture n'atteigne le cache, il lui faut une adresse physique, et la traduction a son propre petit cache, le TLB, avec seulement environ 64 entrées. Un programme qui saute entre plus de pages que cela peut rater le TLB à presque chaque lecture, même quand ses caches de données vont bien. Ce cours construit un TLB et montre comment une page de 2 Mo transforme 250 pages en une seule.

01

Deux sortes d'adresses

Les adresses qu'utilise un programme sont virtuelles : chaque programme croit posséder une longue file de mémoire à partir de zéro. La machine garde la vraie mémoire en adresses physiques et découpe les deux mondes en pages. Une table en mémoire, la table des pages, dit quelle page physique contient chaque page virtuelle. Toute lecture a d'abord besoin de cette traduction : prendre le numéro de page de l'adresse virtuelle, le chercher, et garder la position de l'octet dans la page. C'est le même découpage que la ligne d'un cache, avec un bloc plus gros.

main.pyPython
page_bytes = 4096for address in (0, 4095, 4096, 123456789):    print(address, "-> page", address // page_bytes, "byte", address % page_bytes)1
0 -> page 0 byte 0
4095 -> page 0 byte 4095
4096 -> page 1 byte 0
123456789 -> page 30140 byte 3349
  1. 1Le numéro de page est l'adresse divisée par la taille de page ; le reste est l'octet dans la page.
02

Un cache de traductions

Parcourir la table des pages en mémoire à chaque lecture doublerait le coût d'un accès mémoire : le processeur garde donc ses dernières traductions dans une petite table rapide appelée TLB. Une lecture dont la page est dans le TLB est un succès et ne coûte presque rien. Une lecture dont la page n'y est pas est un défaut de TLB et déclenche un parcours de la table des pages, des dizaines de nanosecondes. Un TLB de données de premier niveau contient environ 64 entrées. À part qu'il garde des pages au lieu de lignes, il fonctionne comme les caches précédents : la moins récemment utilisée part d'abord.

main.pyPython
class TLB:    def __init__(self, entries):        self.entries = entries        self.pages = []        self.hits = 0        self.misses = 0    def access(self, address, page_bytes):        page = address // page_bytes        if page in self.pages:            self.pages.remove(page)            self.pages.append(page)            self.hits += 1            return True        self.misses += 1        self.pages.append(page)        if len(self.pages) > self.entries:            self.pages.pop(0)        return Falsedef tlb_misses(trace, entries, page_bytes):    tlb = TLB(entries)    for address in trace:        tlb.access(address, page_bytes)    return tlb.missesfor n_pages in (48, 64, 65, 80):    trace = [page * 4096 for page in range(n_pages)] * 5    print(n_pages, "pages, 5 rounds:", tlb_misses(trace, 64, 4096), "misses")
48 pages, 5 rounds: 48 misses
64 pages, 5 rounds: 64 misses
65 pages, 5 rounds: 325 misses
80 pages, 5 rounds: 400 misses

Une boucle sur 48 ou 64 pages n'échoue qu'au premier tour. Une page de plus, 65, et le TLB échoue à chaque lecture des 5 tours : 325 défauts sur 325. C'est la même falaise LRU que dans le sujet des ensembles de travail, mais avec des pages. Ce qui compte est la portée : la quantité de mémoire que le TLB couvre d'un coup.

TLB reach = entries × page size(1)64 entrées × 4 Ko = 256 Ko ; avec des pages de 2 Mo, les mêmes 64 entrées couvrent 128 Mo
03

Lire des enregistrements au hasard

Prenez une table de 2 000 enregistrements de 512 octets chacun : un jour de données plus des champs supplémentaires. Elle occupe 1 000 Ko, soit 250 pages de 4 Ko, presque quatre fois les 64 pages que le TLB peut contenir. Lire les enregistrements dans l'ordre est doux : huit enregistrements partagent chaque page, le TLB échoue donc une fois par page, 250 fois. Les lire dans un ordre aléatoire est dur : chaque lecture peut tomber sur l'une des 250 pages et le TLB n'en garde que 64. Le code ci-dessous mesure les deux, avec des pages de 4 Ko et de 2 Mo.

main.pyPython
import randomorder = list(range(2000))shuffled = random.Random(7).sample(order, len(order))for name, records in (("in order", order), ("shuffled", shuffled)):    trace = [record * 512 for record in records]    print(name, "4 KB pages:", tlb_misses(trace, 64, 4096), "- 2 MB pages:", tlb_misses(trace, 64, 2 * 1024 * 1024))
in order 4 KB pages: 250 - 2 MB pages: 1
shuffled 4 KB pages: 1541 - 2 MB pages: 1

Dans l'ordre, les pages de 4 Ko coûtent 250 défauts. Mélangé, elles coûtent 1 541 défauts sur 2 000 lectures, 77 % des lectures, six fois plus. Avec des pages de 2 Mo, les 1 000 Ko tiennent dans une seule page : un défaut quel que soit l'ordre. À 30 ns par parcours, la lecture mélangée passe 46 microsecondes rien qu'en traductions, de quoi faire 100 000 additions.

Les grandes pages en pratique

Sous Linux, on peut demander des grandes pages avec les grandes pages transparentes ou avec des pages hugetlbfs explicites, et les systèmes de trading y logent souvent leurs grosses tables. Le gain se voit pour de grandes tables lues dans un ordre irrégulier, pas pour de petites ni pour des parcours dans l'ordre.

Les grandes pages ne sont pas gratuites

Une grande page demande 2 Mo de mémoire physique contiguë, parfois difficile à trouver sur une machine qui tourne depuis des semaines, et une table plus petite qu'une page occupe quand même toute la page. Allouez-les tôt, au démarrage, pour les quelques tables qui en ont besoin.

Ce que disent les vraies données2 000 enregistrements SPY de 512 octets (1 000 Ko, 250 pages), TLB de 64 entrées
Dans l'ordre des jours : pages de 4 Ko250défauts de TLB, 7 500 ns de parcours
Dans l'ordre des jours : pages de 2 Mo1une page contient toute la table
Par volume croissant : pages de 4 Ko78439 % des lectures ratent le TLB
Par volume croissant : économisé par les grandes pages23,490ns783 parcours évités
Défauts de TLB selon l'ordre de lecture et la taille de page
Jours, 4 Ko250
Volume, 4 Ko784
N'importe quel ordre, 2 Mo1
04

Ce que vous allez construire

Le labo suit le cours : la page d'une adresse, le TLB à remplacement LRU, le décompte des défauts, les pages qu'une trace touche, les adresses d'enregistrements dans un ordre, la comparaison des tailles de page et l'étude sur les enregistrements SPY.

  • Fonction · questionS'appuie sur
  • page_of(address, page_bytes)Quelle page contient cette adresse ?La division entière
  • TLB(entries).access(address, page_bytes)Cette traduction est-elle un succès de TLB ?page_of
  • tlb_misses(trace, entries, page_bytes)Combien de défauts de TLB une trace coûte-t-elle ?TLB
  • pages_touched(trace, page_bytes)Combien de pages différentes une trace touche-t-elle ?page_of
  • record_trace(order, record_bytes)Quelles adresses touche la lecture des enregistrements dans cet ordre ?De l'arithmétique simple
  • compare_pages(trace, entries)Que gagnent les grandes pages ?tlb_misses
  • study(bars)Que font gagner les grandes pages sur les enregistrements SPY ?compare_pagespages_touchedrecord_trace

À retenir

  • La traduction a aussi un cache. Toute lecture a besoin que sa page soit traduite ; le TLB garde environ 64 traductions récentes, et un défaut déclenche un lent parcours de la table des pages.
  • La portée est entrées × taille de page. 64 entrées de 4 Ko couvrent 256 Ko ; une table de 1 000 Ko lue dans un ordre aléatoire échoue à la plupart des lectures.
  • Les grandes pages étendent la portée. Des pages de 2 Mo couvrent 128 Mo avec les mêmes 64 entrées ; la table tenait dans une page et les défauts sont passés de 784 à 1.
Vérification rapide
Un TLB a 64 entrées et les pages font 2 Mo. Quelle quantité de mémoire peut-il couvrir d'un coup ?
Choisissez une réponse.

Sujet suivant : jusqu'ici il y avait un programme et un cœur. Dans Faux partage et remplissage, deux cœurs écrivent dans deux variables différentes qui se trouvent dans la même ligne de cache, et la ligne fait des allers-retours entre eux. Vous comptez les invalidations et les supprimez par remplissage.

Lab : ce qui est noté

7 tâches · 100 pts
  • La page d'une adresse10 pts
  • Un TLB à remplacement LRU25 pts
  • Les défauts de TLB d'une trace10 pts
  • Pages touchées10 pts
  • Lire des enregistrements dans un ordre10 pts
  • Pages de 4 Ko contre 2 Mo15 pts
  • L'étude sur la table SPY20 pts
Explorateur · lab-cl-8
▾ lab-cl-8
▾ data
…
bash · dans le navigateur
learner@quantcraft:~/lab-cl-8$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-cl-8 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