Políticas de cache e desempenho

Escritas, vítimas dirty, memória principal e CPI de caches separadas ou multinível.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

O CPU escreve 7 no endereço 0 e volta a lê-lo. Se a cache conservar o valor novo, essa leitura pode acertar mesmo que a RAM ainda tenha o valor antigo. A política de escrita determina quando a modificação chega ao nível seguinte; a política de alocação determina o que fazer quando a escrita falha.

Write-through e write-back

Write-through (WT): uma escrita que acerta atualiza a cache e envia a escrita para o nível seguinte. Write-back (WB): altera a cache e marca a linha dirty; o nível seguinte pode ficar desatualizado até a linha ser descarregada.

Dirty não significa inválido. V=1,D=1 contém dados válidos e modificados. V=0 não é uma linha utilizável, mesmo que o bit D antigo seja 1.

O modelo WT/no-allocate não instala uma linha por uma escrita que falha. WB/allocate instala-a. São combinações frequentes, não uma equivalência lógica: política de escrita e de alocação são decisões distintas.

OperaçãoWT, no-allocateWB, allocate
Leitura com acertoLer cacheLer cache
Leitura com faltaCarregar linha; V=1Descarregar vítima válida dirty, se houver; carregar linha; V=1,D=0
Escrita com acertoAtualizar cache e nível seguinteAtualizar cache; D=1
Escrita com faltaEscrever no nível seguinte; cache fica igualDescarregar vítima válida dirty; instalar linha, alterar os bytes escritos; V=1,D=1

Em uma escrita parcial de uma linha, a alocação normalmente lê os bytes restantes do nível seguinte. No modelo adotado, se a escrita substitui a linha inteira, não é necessário lê-la antes. Por exemplo, uma cache com uma palavra por linha pode instalar uma escrita de palavra completa sem uma leitura adicional. Esta condição muda a contagem de acessos.

Um traço com vítimas modificadas

Uma falta com vítima dirty tem duas tarefas: conservar o bloco antigo e instalar o pedido. Segue cache e RAM lado a lado, pois uma leitura que acerta devolve o valor mais recente da cache. O traço usa cache direta WB com 2 linhas de 4 B, inicialmente inválida, e operações de palavra completa, com E a escrever e L a ler.

OperaçãoÍndice, etiquetaEventos no nível seguinteEstado relevante depois
E0=70,0Nenhum; escrita cobre a linhaLinha 0: tag 0, V 1, D 1, valor 7
L00,0NenhumDevolve 7
E8=90,1Escrever vítima no endereço 0Linha 0: tag 1, V 1, D 1, valor 9
L41,0Ler linha que começa em 4Linha 1: tag 0, V 1, D 0
L00,0Escrever vítima no endereço 8 e ler linha 0Linha 0: tag 0, V 1, D 0, valor 7

Total: duas leituras e duas escritas de linhas na memória principal. O último acesso devolve 7 porque a primeira vítima já tinha atualizado a memória.

O endereço de uma vítima é reconstruído com a etiqueta antiga, o índice da entrada e deslocamento zero. Usar a etiqueta do pedido escreveria os dados da vítima no sítio errado.

Aplica WT/no-allocate ao mesmo traço. E0 escreve na RAM sem instalar nada; L0 carrega a linha 0. E8 escreve na RAM e mantém na cache o bloco 0; L4 carrega a linha 4; a última L0 acerta.

Os totais coincidem, duas escritas e duas leituras, mas por causas diferentes:

Acesso finalWB: o que aconteceWT: o que acontece
L0 finalFalta; descarrega 9 e carrega 0Acerto na linha guardada
E8Sem tráfego; só marca dirtyEscrita direta na RAM

No traço WB, a leitura final falha e provoca dois acessos; em WT, acerta.

Para reconstruir a vítima no acesso L0, a etiqueta antiga é 1, o índice é 0 e cada linha tem 4 B: (1×2+0)×4=8(1\times2+0)\times4=8. É nesse endereço que se descarrega 9 antes de ler 0.

O que se pode conhecer da memória

Uma linha WB válida e limpa permite conhecer os bytes correspondentes na memória principal, se nenhum agente externo os alterou. Uma linha válida dirty permite conhecer o valor que o processador lê, mas não o valor antigo na memória. Uma etiqueta diferente ou V=0 não prova nada sobre os dados desse endereço na memória.

Um buffer de escrita pode deixar o CPU continuar enquanto uma escrita WT avança. Se o exercício diz que não existe buffer, cobra a espera por escrita. Se existe, considera a capacidade e as condições de bloqueio fornecidas; não acrescentes sempre a latência inteira ao CPI.

Tempo médio de acesso

O modelo seguinte atende cada pedido antes do seguinte, sem sobrepor faltas. Para um nível, se a penalidade é o tempo adicional depois de verificar a falta:

TMAM=tacerto+m pfalta.TMAM=t_{\rm acerto}+m\,p_{\rm falta}.

Com acerto de 1 ns, taxa de falta 5% e penalidade 20 ns, o TMAM é 2 ns. Se os 20 ns já incluíssem a procura inicial, a conta teria de evitar contá-la duas vezes.

De taxas de falta para CPI

Este modelo soma ciclos de espera que não se sobrepõem e não estão já no CPI de base. Caches I e D separadas; uma obtenção de instrução por instrução e fração rr de instruções com um acesso a dados:

CPI=CPIbase+mIpI+r mDpD.CPI=CPI_{\rm base}+m_Ip_I+r\,m_Dp_D.

Com base 1,2; mI=0,01m_I=0,01; mD=0,04m_D=0,04; r=0,30r=0,30 e ambas as penalidades 80 ciclos:

CPI=1,2+0,01×80+0,30×0,04×80=2,96.CPI=1,2+0,01\times80+0,30\times0,04\times80=2,96.

Para uma cache unificada, o número médio de acessos é 1+r1+r: CPIprot=(1+r)mpCPI_{\rm prot}=(1+r)mp. Instruções que realizem vários acessos exigem a sua contagem real. Penalidades dirty podem ser uma parcela adicional, ponderada pela frequência dessas vítimas.

Recuperar a mistura a partir das esperas

A equação também permite obter uma grandeza que não foi medida diretamente. Num CPU de 2 GHz, cada ciclo demora 0,5 ns, por isso uma falta que acrescenta 50 ns custa 100 ciclos.

Suponhamos uma cache unificada com taxa de falta 9% por acesso e 12 ciclos de espera por instrução. Cada instrução faz uma obtenção e, se for load/store, mais um acesso a dados.

Se rr é a fração de instruções que são loads/stores, com uma obtenção por instrução e no máximo um acesso a dados, as esperas são:

12=(1+r)×0,09×100.12=(1+r)\times0,09\times100.

Divide primeiro pela espera média de um acesso:

1+r=129=43.1+r=\frac{12}{9}=\frac43.

A obtenção obrigatória explica o primeiro acesso. Subtraí-la dá r=1/3r=1/3, ou 33,33% de instruções com acesso a dados. Se fossem caches I/D separadas e os 12 ciclos contassem apenas dados, não haveria esse 1: o denominador e a equação seriam outros.

Neste modelo, 0≤r≤10\le r\le1. Um resultado fora desse intervalo indica que os dados não cabem nas hipóteses: pode haver várias operações de memória por instrução, ou custos de escrita não incluídos. Também é necessário partir só da parcela de esperas. Usar o CPI total como se toda a execução fosse protelamento mistura grandezas diferentes.

Se a fonte dá uma razão entre acertos e faltas, transforma-a antes de calcular. Acertos nove vezes mais frequentes que faltas significam h=9mh=9m e h+m=1h+m=1, logo m=1/10m=1/10. A taxa de falta não é 1/91/9: essa razão tem acertos no denominador.

Vários níveis de cache

Uma falta em L1 consulta L2. Taxa local de L2 é a fração dessas consultas que falha. Taxa global de L2 é a fração de todos os pedidos originais que chega à memória. Se há um pedido por instrução, m2,g=m1m2,lm_{2,g}=m_1m_{2,l}.

TMAM=t1+m1(t2+m2,lpRAM).TMAM=t_1+m_1(t_2+m_{2,l}p_{\rm RAM}).

Exemplo: t1=1t_1=1 ciclo, m1=0,10m_1=0,10, t2=8t_2=8 ciclos, m2,l=0,20m_{2,l}=0,20, RAM 80 ciclos adicionais. O TMAM é 1+0,10(8+0,20×80)=3,41+0,10(8+0,20\times80)=3,4 ciclos. A taxa global que chega à RAM é 2%, não 20%.

Para CPI de CPU a 4 GHz, base 1, faltas L1 de 2% por instrução, consulta L2 de 5 ns e faltas RAM globais 0,5% com 100 ns adicionais: p2=20,pR=400p_2=20,p_R=400 ciclos. Logo CPI=1+0,02×20+0,005×400=3,4CPI=1+0,02\times20+0,005\times400=3,4. Sem L2 seria 1+0,02×400=91+0,02\times400=9. A rapidez relativa é 9/3,4=2,6479/3,4=2,647, se NN e a frequência forem iguais.

Tráfego entre níveis com write-back

Uma falta em L1 e uma escrita na RAM são eventos diferentes. Em WB, uma escrita pode falhar para carregar uma linha e só enviar a modificação mais tarde, ao substituir a vítima. Saber a taxa de faltas não basta para contar descargas: é preciso saber quantas vítimas válidas estão dirty e se há flush final.

Segue duas escritas de palavra, E0=7 e E64=9, com estas hipóteses: L1 direta WB/allocate de uma linha de 16 B; L2 direta WT de quatro linhas de 16 B; ambas vazias. Escritas parciais em L1 leem a linha antes de a alterar. Cada descarga de L1 entrega a linha inteira a L2; L2 envia essa escrita inteira à RAM. Não há buffers nem flush final. A memória em ambos os endereços começa a zero.

PassoPedidoEfeito na RAM
1E0 falha em L1; L1 pede a linha 0 a L2, que também falhaLeitura da linha 0
2L1 modifica a palavra 0 para 7Nenhum; L1 fica dirty
3E64 falha em L1; a vítima 0 é descarregada para L2L2 acerta e, por WT, escreve a linha 0 na RAM
4L1 pede a linha 64; L2 falha e substitui a sua linha 0 limpaLeitura da linha 64
5L1 modifica a palavra 64 para 9Nenhum; L1 fica dirty

São duas leituras e uma escrita de linha na RAM. A descarga da vítima atravessou L2 num acerto, mas gerou escrita porque L2 é WT. A RAM termina com 7 no endereço 0 e ainda 0 no endereço 64; o CPU lê 9 nesse último por acerto em L1. Um flush final acrescentaria outra escrita de linha na RAM, segundo as mesmas regras.

A taxa global m1m2,lm_1m_{2,l} conta pedidos de leitura que faltam nos dois níveis, quando cada taxa usa o seu denominador. Não a apliques a todas as escritas WB. Para contar tráfego de escritas, segue separadamente carregamentos, descargas e a alocação de cada nível.

Exercícios

Contar escritas e leituras

Cache WB/allocate direta, 2 linhas de 4 B, vazia. O modelo dispensa ler uma linha que será totalmente escrita e não faz flush final. Palavras completas: E0=7, L0, E8=9, L4, L0. Quantos acessos à memória principal, contando leitura ou escrita de linha como um?

Pista
Uma escrita de palavra cobre a linha inteira.
Solução

E0 não acede à RAM; L0 acerta; E8 descarrega 0; L4 carrega 4; L0 descarrega 8 e carrega 0. Total 4: 2 leituras+2 escritas.

Erros frequentes

Cobrar carga desnecessária para escrita de linha completa ou esquecer o write-back da vítima.

Voltar à explicação
Preservar bytes não escritos

Cache WB com linha 16 B; uma escrita de 4 B falha e escolhe vítima válida dirty. A política lê a linha nova antes de alterar 4 B. Quantas transferências de linha com a memória?

Pista

A vítima deve ser conservada; a linha nova tem bytes não escritos.

Solução

Total 2, porque descarrega 16 B antigos; carrega 16 B novos; altera 4 B na cache e marca dirty.

Erros frequentes

Aplicar a exceção de linha totalmente escrita a uma escrita parcial.

Voltar à explicação
Combinar I e D

Base CPI 1,2; faltas I de 1%, faltas D de 4%; 30% das instruções fazem um acesso a dados; penalidade 80 ciclos. Calcula CPI.

Pista
A taxa D tem como denominador acessos a dados.
Solução

CPI=2,96, ou seja, I acrescenta 0,8 e D acrescenta 0,96.

Erros frequentes

Aplicar miss D a todas as instruções ou somar taxas sem os respetivos denominadores.

Voltar à explicação
Usar a taxa local certa

L1 acerto 1 ciclo, miss 10%; L2 consulta 8 ciclos, miss local 20%; RAM 80 ciclos adicionais. Calcula TMAM.

Pista
Só 10% dos pedidos chegam a L2.
Solução
TMAM=3,4 ciclos; taxa RAM global=0,10×0,20=2%.

Erros frequentes

Cobrar 8 ciclos a todos os pedidos ou tratar 20% local como 20% global.

Voltar à explicação
O que uma linha dirty permite concluir

Cache WB, sem agentes externos nem buffers de escrita. A linha válida do endereço X é dirty e contém X=9. Não sabemos o valor inicial nem houve write-back. O que sabemos sobre uma leitura do CPU e sobre a RAM?

A tua resposta

Pista

Distingue a cópia que serve a leitura da cópia no nível seguinte.

Solução

O CPU obtém 9 por acerto. A RAM conserva o valor anterior, que não foi dado. Dirty não permite afirmar que esse valor é diferente de 9, apenas que não há garantia de igualdade.

  • O CPU lê 9; o valor atual na RAM é indeterminado.. A linha válida responde ao CPU, mas dirty não revela o valor anterior da RAM.
  • O CPU e a RAM têm ambos 9.. WB ainda pode não ter descarregado a modificação.
  • O CPU não pode ler porque dirty significa inválida.. Dirty indica modificação, não invalidade.

Erros frequentes

Inventar o valor antigo ou concluir que dirty prova necessariamente uma diferença de valores.

Voltar à explicação
Recuperar acessos a dados a partir das esperas

Um CPU de 2 GHz tem cache unificada com taxa de falta 9% por acesso. Cada falta acrescenta 50 ns, sem sobreposição. Há uma obtenção por instrução e cada load/store faz exatamente um acesso adicional; as outras instruções não acedem a dados. Mediram-se 12 ciclos de espera por instrução, sem contar o CPI de base. Determina a fração de loads/stores. No mesmo modelo, seria possível medir apenas 8 ciclos de espera por instrução?

Pista

Mesmo sem loads/stores, continuam a obter-se instruções.

Solução

Cada ciclo dura 0,5 ns, por isso a penalidade é 50/0,5=100 ciclos. Escreve 12=(1+r)×0,09×100; daí 1+r=4/3 e r=1/3. Mesmo com r=0, a obtenção produz 0,09×100=9 ciclos de espera por instrução. O valor 8 daria r=−1/9 e é incompatível com estas hipóteses. Não é uma fração válida de instruções; seria necessário rever a taxa, a penalidade ou o modelo.

Confere a tua resposta:

  • Converti 50 ns para 100 ciclos a 2 GHz.
  • Usei 1+r acessos por instrução na cache unificada.
  • Obtive r=1/3, isto é, 33,33%.
  • Expliquei por que 8 ciclos de espera seriam incompatíveis.
Voltar à explicação
Uma descarga pode chegar à RAM mesmo acertando em L2

E0=7 e E64=9 escrevem palavras de quatro bytes. L1 direta tem uma linha de 16 B, WB/allocate; L2 direta tem quatro linhas de 16 B, WT. Ambas estão vazias e a RAM começa a zero. Uma escrita parcial em L1 carrega antes a linha inteira; a descarga de L1 entrega a linha inteira a L2 e L2 envia-a à RAM, tanto no acerto como na falta. Leituras que falham em L2 carregam a linha. Sem buffers nem flush final, conta as leituras/escritas de linhas da RAM e indica os valores que RAM e CPU têm nos dois endereços. O que mudaria com flush final de L1?

Solução

E0 provoca uma leitura da linha 0 até L1 e deixa aí 7, dirty. E64 expulsa essa linha: L2 ainda a contém, mas a escrita WT atualiza a RAM com 7. Depois carrega a linha 64 da RAM e altera-a para 9 só em L1. Há duas leituras e uma escrita. RAM guarda 7 em 0 e 0 em 64; os valores mais recentes para o CPU são 7 e 9. O último está em L1, mas 0 já não está. Uma leitura posterior de 0 precisaria de o carregar e primeiro descarregaria a vítima 64. O flush final descarrega a linha 64 por L2 e acrescenta uma escrita na RAM, que passa a conter 9. Multiplicar taxas de faltas não contaria a escrita que acertou em L2.

Confere a tua resposta:

  • Separei os dois carregamentos da descarga dirty.
  • Obtive duas leituras e uma escrita de linha na RAM.
  • Mantive 7 na RAM em 0 e 9 apenas na L1 em 64.
  • Expliquei por que o flush final acrescentaria outra escrita.
Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.