σμ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 AcademyRoadmapsRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
RoadmapsRoteiros
AO
+1,2 mil alunos
Entrar
  • 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 AcademyRoadmapsRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
RoadmapsRoteiros
AO
+1,2 mil alunos
Entrar
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Roteiro de Cache locality›Módulo 1 · Caches do zero›Tópico 1.1·~40 minIniciante

A hierarquia de memória e os números de latência

Posição no roteiroMódulo 1 de 3 · Tópico 1 de 4
1.1 A hierarquia de memória e os números de latência
—Nota do lab— / 100XP total—Sequência—

6 min de leitura4 exemplos de código

  1. 01Por que a memória, e não a aritmética, define a velocidade
  2. 02Quanto custa um acesso
  3. 03O tempo médio de acesso
  4. 04Quem responde e quem custa
  5. 05Ler uma tabela real
  6. 06O que você vai construir

Um processador soma dois números em uma fração de nanossegundo, mas buscar um número que não está em nenhum cache pode levar 80 ns. Esta aula transforma esses números de latência em uma só cifra, o custo médio de um acesso à memória, e mostra qual nível de memória consome o seu tempo.

01

Por que a memória, e não a aritmética, define a velocidade

Um programa de trading passa a maior parte da vida esperando dados: um preço, uma ordem, uma linha de tabela. A aritmética sobre esses dados é quase de graça, mas os dados precisam antes viajar da memória até o processador, e quanto mais longe estão, mais demora. Pense numa mesa, uma estante, o andar de uma biblioteca e um armazém do outro lado da cidade. Os poucos papéis da mesa são instantâneos, a estante leva segundos, a biblioteca um minuto e o armazém uma tarde. Os computadores copiam os dados mais usados para memórias pequenas e rápidas junto ao processador, chamadas caches, para que a maioria dos pedidos seja atendida na mesa.

DefiniçãoLatência

O tempo entre pedir um valor e tê-lo, medido aqui em nanossegundos (bilionésimos de segundo).

Um núcleo de servidor típico tem três caches na frente da memória principal. Chamamos de L1, L2 e L3, e a memória principal de RAM. Um pedido atendido por um cache é um acerto; um pedido que precisa seguir para o próximo nível é uma falta. A tabela abaixo põe as quatro latências lado a lado.

main.pyPython
LATENCY_NS = {"L1": 1.0, "L2": 4.0, "L3": 15.0, "RAM": 80.0}for level, ns in LATENCY_NS.items():    print(level, ns, "ns", ns / LATENCY_NS["L1"], "x L1")
L1 1.0 ns 1.0 x L1
L2 4.0 ns 4.0 x L1
L3 15.0 ns 15.0 x L1
RAM 80.0 ns 80.0 x L1

Cada nível é várias vezes mais lento que o de cima, e a RAM é 80 vezes mais lenta que a L1. Toda esta habilidade trata de garantir que a maioria dos acessos seja atendida perto do topo.

02

Quanto custa um acesso

Um acesso começa na L1. Se o valor está lá, o acesso custa a latência da L1 e acaba. Se não, o processador pergunta à L2, depois à L3 e depois à RAM, que sempre tem o valor. Cada nível consultado custa tempo, acerte ou não, então um acesso encontrado na L3 pagou L1, L2 e L3.

  1. 1
    Perguntar à L1Pague 1 ns. Um acerto termina o acesso.
  2. 2
    Em caso de falta, perguntar à L2Pague mais 4 ns. Um acerto termina o acesso.
  3. 3
    Em caso de falta, perguntar à L3Pague mais 15 ns. Um acerto termina o acesso.
  4. 4
    Em caso de falta, ir à RAMPague mais 80 ns. A RAM sempre tem o valor.
main.pyPython
LATENCY_NS = {"L1": 1.0, "L2": 4.0, "L3": 15.0, "RAM": 80.0}cost_found_in_l3 = LATENCY_NS["L1"] + LATENCY_NS["L2"] + LATENCY_NS["L3"]print(cost_found_in_l3, "ns")
20.0 ns

Um acesso atendido pela L3 custa 20 ns, não 15: o 1 ns e os 4 ns gastos nas duas faltas anteriores fazem parte da conta.

As taxas de acerto são locais

Cada taxa de acerto conta só os acessos que chegam àquele nível. Uma taxa de acerto da L2 de 0,8 significa 80% dos acessos que falharam na L1, não 80% de todos. Confundir as duas é o erro mais comum deste tópico.

03

O tempo médio de acesso

Nenhum acesso é típico, então pedimos a média de muitos acessos. Pondere o custo de cada caminho por sua frequência. Todo acesso paga a latência da L1; só a parte que falha na L1 paga a L2; só a que falha nas duas paga a L3; e assim por diante. Escrito como uma expressão, com parênteses que se aninham como os níveis:

AMAT = t₁ + (1 − h₁) · (t₂ + (1 − h₂) · (t₃ + (1 − h₃) · t_RAM))(1)t₁, t₂, t₃ e t_RAM são as latências; h₁, h₂ e h₃ são as taxas de acerto locais de L1, L2 e L3

Este é o tempo médio de acesso à memória. Leia os parênteses de dentro para fora: o mais interno é o que custa uma falta na L3, o seguinte soma a visita à L3, e assim por diante até a visita à L1 que todo acesso paga.

main.pyPython
LATENCY_NS = {"L1": 1.0, "L2": 4.0, "L3": 15.0, "RAM": 80.0}h1, h2, h3 = 0.9, 0.8, 0.7t = LATENCY_NSamat = t["L1"] + (1 - h1) * (t["L2"] + (1 - h2) * (t["L3"] + (1 - h3) * t["RAM"]))1print(round(amat, 2), "ns")
2.18 ns
  1. 11 - h é a parte dos acessos que falham, então cada parêntese é multiplicado pela parte que chega até ali.

Com 90% dos acessos acertando na L1, a média ainda é 2,18 ns, mais que o dobro da latência da L1. Os poucos acessos que vão fundo são tão caros que puxam a média. Por isso uma taxa de acerto que parece excelente ainda pode esconder um programa lento.

Ciclos ou nanossegundos?

Os fabricantes informam a latência em ciclos do processador: 4 ciclos a 4 GHz são 1 ns. Usamos nanossegundos para comparar os níveis num relance. Estes números são típicos, não exatos: chips reais diferem por um fator de dois para mais ou para menos.

04

Quem responde e quem custa

Duas perguntas parecem iguais mas têm respostas diferentes. Qual nível atende os acessos? E qual nível leva o tempo? A primeira conta acessos, a segunda conta espera. Um nível é alcançado por uma parte dos acessos e cada visita custa a sua latência, então um nível raramente alcançado mas lento ainda pode dominar a espera.

main.pyPython
h1, h2, h3 = 0.9, 0.8, 0.7served = [h1, (1 - h1) * h2, (1 - h1) * (1 - h2) * h3, (1 - h1) * (1 - h2) * (1 - h3)]reach = [1.0, 1 - h1, (1 - h1) * (1 - h2), (1 - h1) * (1 - h2) * (1 - h3)]1cost = [r * ns for r, ns in zip(reach, [1.0, 4.0, 15.0, 80.0])]2print([round(x, 3) for x in served])print([round(c / sum(cost), 3) for c in cost])
[0.9, 0.08, 0.014, 0.006]
[0.459, 0.183, 0.138, 0.22]
  1. 1reach é a parte dos acessos que visitam cada nível: todos visitam a L1.
  2. 2sum(cost) é o tempo médio de acesso: os mesmos 2,18 ns de antes.

A RAM atende só 0,6% dos acessos mas responde por 22% do tempo de espera, enquanto a L1 atende 90% deles e leva 46% do tempo. Este é o fato central por trás de toda otimização desta habilidade: não conte acessos, conte para onde vai o tempo.

05

Ler uma tabela real

Quanto isso importa numa tabela real? A tabela de barras diárias do SPY do laboratório tem 5.405 linhas e cinco colunas (abertura, máxima, mínima, fechamento, volume), ou seja, 27.025 valores. Leia cada valor uma vez em três condições: caches quentes onde quase tudo acerta, caches mornos e caches frios onde metade dos acessos falha em cada nível.

O que dizem os dados reaisBarras diárias do SPY, 2005 a 2026
Valores na tabela27,0255.405 linhas × 5 colunas
Frio contra quente15.9×mais lento para a mesma tabela
Acesso médio, caches quentes1.05nstaxas de acerto 0,99 · 0,95 · 0,90
Acesso médio, caches frios16.75nsa RAM é 60% dessa espera
Tempo para ler a tabela uma vez, em microssegundos
Caches quentes28
Caches mornos59
Caches frios453
06

O que você vai construir

O laboratório transforma esta aula em seis funções pequenas, cada uma construída sobre as anteriores, e termina precificando a leitura da tabela real do SPY. Aqui estão elas com a pergunta que cada uma responde.

  • Função · perguntaBaseia-se em
  • average_access_time(hit_rates)Quanto custa um acesso em média?A tabela de latências
  • slowdown(hit_rates)Quantas vezes mais lento que acertar sempre na L1?average_access_time
  • levels_served(hit_rates)Qual nível atende os acessos?Taxas de acerto locais
  • time_shares(hit_rates)Qual nível leva o tempo?average_access_time
  • scan_time_us(n_accesses, hit_rates)Quanto tempo levam n acessos?average_access_time
  • study(bars)Quanto custa ler toda a tabela do SPY?scan_time_ustime_shares

Pontos-chave

  • Conte para onde vai o tempo. A parte dos acessos que um nível atende e a parte do tempo que ele custa são números diferentes, e um nível raro mas lento pode dominar.
  • As taxas de acerto são locais. A taxa de cada nível conta só os acessos que chegam a ele, então a parte que ele atende é o produto das faltas acima e da sua própria taxa.
  • A média é um aninhamento de parênteses. AMAT = t₁ + falta₁ × (t₂ + falta₂ × (…)) é o número que cada tópico seguinte tenta reduzir.
Verificação rápida
Uma taxa de acerto da L1 de 0,95. Dos acessos que chegam à L2, metade acerta. Que parte de todos os acessos a L2 atende?
Escolha uma resposta.

Próximo tópico: esta aula tomou as taxas de acerto como dadas. Em Linhas de cache e localidade espacial você constrói o cache que as produz e descobre por que ler um valor ao lado de outro recém-lido é quase de graça.

Lab: o que é avaliado

6 tarefas · 100 pts
  • Tempo médio de acesso20 pts
  • Lentidão frente à L110 pts
  • Quem atende os acessos15 pts
  • Quem leva o tempo20 pts
  • O tempo de n acessos15 pts
  • O estudo com a tabela do SPY20 pts
Explorador · lab-cl-1
▾ lab-cl-1
▾ data
…
bash · no navegador
learner@quantcraft:~/lab-cl-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-cl-1 volta aos arquivos iniciais e o terminal é limpo. Sua solução atual será perdida — isso não pode ser desfeito.

Será redefinido
  • main.py → código inicial
  • Histórico do terminal e saída dos testes
  • Alterações não enviadas
Será mantido
  • Melhor nota do lab
  • Seu XP e sua sequência
  • Progresso da aula e anotações