# Cache do processador

Cache do processador (em inglês: CPU cache) é uma memória de acesso rápido. É usada pela Unidade Central de Processamento (CPU, o processador) com o objetivo de reduzir o tempo médio de acesso aos dados armazenados na memória. A cache é uma memória de pouco espaço, porém muito mais rápida e armazena as informações que são usadas com mais frequência pela CPU.
Quando a CPU precisa buscar uma informação na memória, ela busca primeiro pela cache. Se não encontrado, busca-se na Memória Principal, então devolve a informação para a CPU e armazena esta informação na cache.
Com os avanços tecnológicos, vários tipos de cache foram desenvolvidos. Atualmente há cache em processadores, discos rígidos, sistemas, servidores, nas placas-mãe, clusters de bancos de dados, entre outros. Qualquer dispositivo que requeira do usuário uma solicitação/requisição a algum outro recurso, seja de rede ou local, interno ou externo a essa rede, pode requerer ou possuir de fábrica o recurso de cache.
Por ser mais caro, o recurso mais rápido não pode ser usado para armazenar todas as informações. Sendo assim, usa-se o cache para armazenar apenas as informações mais frequentemente usadas. Nas unidades de disco também conhecidas como disco rígido (em inglês: hard drive, HD), também existem chips de cache nas placas eletrônicas que os acompanham.

## Funcionamento

Cache (do inglês, escondido) é uma memória interna ao processador usada para armazenamento temporário de dados que são usados com mais frequência pelo processador.
Outra definição mais precisa poderia ser: uma área de armazenamento temporária dentro do processador onde os dados frequentemente usados são acessados de forma mais rápida, sem necessidade de acesso à memória principal.
Quando a CPU necessita de um determinado endereço que está armazenado na memória, o primeiro lugar a buscar este endereço é na memória cache. Se o conteúdo está na cache, ocorre o acerto na cache, chamado de cache hit (quando o conteúdo requisitado pelo CPU é encontrado na cache), fazendo a informação ser acessada pela CPU sem necessidade de acesso à memória principal. Se o conteúdo não está na cache, ocorre uma falta de cache, chamado de cache miss (quando o conteúdo requisitado pela CPU não esta presente na cache), o que leva a CPU a buscar essa informação na memória principal. Como provavelmente essa informação será requisitada novamente (localidade temporal) o dado que foi buscado na RAM é copiado na cache.
Como a cache possui capacidade de armazenamento extremamente limitada (algo comum de acontecer devido ao seu custo), os novos dados que chegam da memória principal precisam ocupar o lugar de dados já presentes na cache provocando assim a evasão de dados menos recentes. A forma (heurística) utilizada para selecionar o elemento a ser retirado é conhecida como política de troca (replacement policy). Uma política de troca muito popular é a LRU (least recently used), que significa algo como “elemento menos usado recentemente”.
Quando um dado é escrito no cache, ele deve ser gravado no local de armazenamento em algum momento. O momento da escrita é controlado pela política de escrita (write policy). Existem diferentes políticas. A política de write-through (algo como “escrita através”) funciona da seguinte forma: a cada vez que um elemento é colocado no cache, ele também é gravado no local de armazenamento original. Alternativamente, pode ser utilizada a política de write-back (escrever de volta), onde as escritas não são directamente espelhadas no armazenamento. Ao invés, o mecanismo de cache identifica quais de seus elementos foram sobrepostos (marcados como sujos) e somente essas posições são colocadas de volta nos locais de armazenamento quando o elemento for retirado do cache. Por essa razão, quando ocorre um cache miss (falta de acesso ao cache pelo fato de um elemento não existir nele) em um cache com a política write-back, são necessários dois acessos à memória: um para recuperar o dado necessário e outro para gravar o dado que foi modificado no cache.
O mecanismo de write-back pode ser accionado por outras políticas também. O cliente pode primeiro realizar diversas mudanças nos dados do cache e depois solicitar ao cache para gravar os dados no dispositivo de uma única vez.
Os dados disponíveis nos locais de armazenamento original podem ser modificados por outras entidades diferentes, além do próprio cache. Nesse caso, a cópia existente no cache pode se tornar inválida. Da mesma forma, quando um cliente atualiza os dados no cache, as cópias do dado que estejam presentes em outros caches se tornarão inválidas. Protocolos de comunicação entre gerentes de cache são responsáveis por manter os dados consistentes e são conhecidos por protocolos de coerência.

## Princípio da localidade de referência

Podemos definir resumidamente localidade de referência como o método em que os dados são escritos/levados ate a memória cache consequentemente até a CPU. Existem dois tipos de localidade de Referência:

### Localidade Temporal

O processador, ao longo de sua execução poderá requisitar uma informação que não esteja na cache. Isso faz com que esta informação seja buscada na memória Principal. Como a há uma grande probabilidade de essa informação ser executada novamente em um tempo próximo, ela é guardada (uma cópia) na memória cache. Desta maneira essa informação não precisará mais ser buscada na MP por um tempo.

### Localidade Espacial

Quando uma informação é buscada na MP, a localidade temporal faz com que esta informação seja copiada para a cache, porém, também haverá uma grande possibilidade de suas informações vizinhas serem requisitadas em um futuro próximo. Deste modo, junto com a informação requisitada, os vizinhos também serão copiados para a cache. As duas localidades temporal e espacial ocorrem juntas quando a informação é requisitada da MP.

## Organizações de Memória Cache

Dados são transferidos entre a memória principal e a memória cache em blocos de tamanho fixos, chamados de blocos de cache, blocos de dados, blocos de memória ou linhas de cache. Uma linha de cache é a menor porção de dados que pode ser mapeada na cache. Memórias cache são organizadas através de blocos de dados que podem ser organizados em conjuntos (sets).
Quando uma linha de cache é copiada da memória principal para a memória cache, uma entrada de cache é criada. A entrada de cache conterá tanto os dados copiados quanto o endereço requisitado da memória (chamado de tag).
Há três políticas de cachê disponíveis para a colocação de um bloco de memória na cache: Mapeamento direto (direct-mapping), totalmente associativa (fully associative) e associativa por conjunto (set-associative). Originalmente, esse conjunto de organizações de cache era descrito usando o termo "mapeamento de congruência" (congruence mapping).

### Estrutura de uma entrada de cache

Entradas de linha de cache normalmente têm a seguinte estrutura:
| tag | linha de cache | bits de flag |
O bloco de dados (linha de cache) contém os dados que foram buscados da memória principal. A tag contém (partes d') o endereço dos dados que foram buscados da memória principal. Os bits de flag (flag bits) serão discutidos mais adiante.
O "tamanho" da cache é a quantidade de dados da memória principal que ela pode armazenar. Esse tamanho pode ser calculado como o número de bytes salvos em cada bloco de dados vezes o número de blocos salvos no cachê. Os bits de tag, flag e código de correção de erro não são incluídos no cálculo, embora afetem a área física da cache.

### Estrutura do endereço de memória

Um endereço efetivo de memória que segue um determinado bloco de memória (linha de cache) é dividido (de MSB para LSB) em Tag, índice (ou linha) e offset (afastamento) do bloco (por vezes também chamado de apenas "offset").
* A tag contém os bits mais significativos do endereço na memória principal que foi acessado para salvar a informação na cache. É usado para validar se a linha procurada é a mesma que está na cache. Isso é feito testando a tag contra todas as linhas do set atual (o set atual é especificado pelo índice) para ver se esse set contém o endereço desejado. Se sim, ocorre um acerto de cache (cache hit). O tamanho da tag em bits é de:
* O índice descreve em qual set da cache os dados foram colocados em. O tamanho do índice é de $\lceil \log _{2}(s)\rceil$ bits para s sets.
* O offset do bloco especifica os dados desejados dentro do bloco de dados, que por sua vez está dentro da linha de cache. Normalmente o endereço efetivo está em bytes, então o tamanho do offset é de $\lceil \log _{2}(b)\rceil$ bits, onde b é o tamanho de bytes por bloco de dados.

### Bits de flag

Uma cache de instruções só precisa de um bit de flag por entrada de linha de cache: Um bit válido (valid bit). O bit válido indica se um dado bloco de cache foi carregado com dados válidos ou não.
Ao ser ligado, o hardware define todos os bits válidos em todos os caches como "inválidos". Alguns sistemas também definem um bit válido como "inválido" em outras ocasiões, como quando um hardware percebe que certos blocos de dados no cache local não estão sendo utilizados e deveriam ser marcados como inválidos.
Uma cache de dados normalmente precisa de dois bits de parada por linha de cache — um bit válido e um "bit sujo" (dirty bit). Ter um bit sujo ativo indica que a linha de cache já foi modificada desde que ela foi lida da memória principal, indicando que o processador escreveu dados nessa linha e que o valor novo não foi refletido na memória principal.

### Mapeamento direto

Em uma estrutura de mapeamento direto, a cache é organizada em múltiplos sets, com uma única linha de cache por set. A cache pode ser representada visualmente por uma matriz n × 1.

#### Colocando um bloco na cache

* O set é determinado pelos bits de índice, os quais são derivados do endereço do bloco de memória.
* O bloco de memória é colocado dentro do set identificado e a tag é registrada no campo de tag associado ao set.
* Se a linha de cache estava anteriormente ocupada, então os novos dados substituem o bloco de memória na cache.

#### Procurando uma palavra na cache

* O set é identificado pelos bits de índice do endereço.
* Os bits de tag derivados do endereço do bloco de memória são comparados com os bits de tag associados com o set. Se a tag é correspondente, então há um acerto de cache (cache hit) e se retorna o bloco de cache ao processador. Caso contrário, há um erro de cache (cache miss) e o bloco de memória é buscado da memória inferior (como a memória principal ou disco).

#### Vantagens

* Esta política de cache é eficiente em relação à energia, visto que evita a busca por todas as linhas de cache.
* Esta política de cache, e a sua política de substituição equivalente, são simples.
* Usa hardware barato, já que só uma tag precisa ser checada por vez.

#### Desvantagem

* Possui uma taxa de acerto de cache menor, já que só há uma linha de cache por set. Cada vez que uma nova memória é referenciada para o mesmo set, a linha de cache é substituída, o que causa erro de conflito (conflict miss).

#### Exemplo

No início do mapeamento, cada bloco da memória principal tem sua linha exclusiva mapeada na cache. Este mapeamento é facilmente implementado. Tudo começa com o endereço da memória principal. Através deste endereço, para o acesso à cache, deve-se identificar os três campos: TAG, índice (ou linha) e endereço (ou WORD).
Para achar o endereço da palavra, é necessário fazer uma simples conta de logaritmo, tendo em base a quantidade de bytes por linha da cache. LOG$_2$ Nr bytes. Para achar o índice, deve levar em conta o número de linhas que possui a cache, fazendo o mesmo cálculo de logaritmo: LOG$_2$ Nr Linhas O restante será designado a tag.
| tag | índice | endereço |
Suponha, em um exemplo, que o tamanho do endereço da linha seja de 32 bits, e a cache possui 1024 linhas com 64 Bytes cada linha.
Log2 64 = 6 bits para endereço Log2 1024 = 10 bits para índice. 32- (10+6)=16 bits para tag.
Na operação de leitura, a CPU envia um endereço de 32 bits para o circuito de controle da cache que já identifica os campos para começar a pesquisa nas linhas. Inicialmente começando pelo índice, onde a busca ocorre para tentar achar a linha desejada. Após, o próximo passo é comparar os valores da tag do endereço com o valor da tag da linha. Se forem iguais, em seguida, a palavra que esta na linha (6 últimos bits) é transferida pra CPU. Caso os valores das tags não forem iguais, isso significa que a linha desejada pela CPU não esta na cache, portanto é buscada na MP e transferida para a mesma linha, substituindo-a.

### Totalmente associativa

Em uma cache totalmente associativa, a cache é organizada em um único set de cache com múltiplas linhas de cache. Um bloco de memória pode ocupar qualquer uma das linhas de cache. A organização da cache pode ser representada como uma matriz de fileira única 1 × m.

#### Colocando um bloco na cache

* A linha de cache é selecionada com base no bit válido associado com a mesma. Se o bit válido é 0, o novo bloco de memória pode ser colocado na linha de cache; caso contrário terá de ser colocado em outra linha de cache com um bit válido igual a 0.
* Se a cache estiver completamente ocupada então um bloco é ejetado e o bloco de memória é colocado nessa linha de cache.
* O ejetar do bloco de memória é decidido pela política de substituição.

#### Procurando uma palavra na cache

* É comparado a tag de cada linha na cache com a tag do endereço apresentado pela CPU. Se achou, há um acerto de cache. Caso contrário, há um erro de cache e busca-se o endereço na memória principal, guardando-o na cache.
* Baseado no offset, um byte é selecionado e transferido para a CPU.

#### Vantagens

* A estrutura de cache totalmente associativa nos dá a flexibilidade de colocar um bloco de memória em qualquer linha de cache, logo, há utilização total da cache.
* Essa política de cachê tem as melhores taxas de acerto de cache.
* Nos dá a flexibilidade de utilizar uma grande variedade de algoritmos de substituição se houver um erro de cache.

#### Desvantagens

* A política é lenta, já que toma tempo para iterar sobre todas as linhas.
* A política usa muita energia, já que tem de iterar pelo set inteiro para localizar um bloco.
* O mais caro de todos os métodos, por conta do alto custo do hardware de comparação associativa.

### Associatividade por Conjunto (N-Way)

Este tipo de organização intercala as vantagens dos outros dois mapeamentos citados acima, acabando com a comparação exaustiva dos campos tag (causado no mapeamento totalmente associativo) e o problema de conflito de endereços por uma mesma linha na cache (causado no mapeamento direto). Neste caso, a cache nada mais é do que uma série de conjuntos, constituídos por uma série de linhas em cada conjunto. A sigla N-Way significa o tamanho dos conjuntos da cache, onde N é a quantidade de palavras em um conjunto.
Pode ser imaginada como uma matriz n × m. O cache é dividido em "n" conjuntos e cada set contém "m" linhas de cache. Um bloco de memória é primeiro mapeado para um set e depois colocado em qualquer linha de cache daquele set.
Muitas caches de processador em designs atuais são ou mapeadas diretamente, associadas por conjunto 2-way, ou associadas por conjunto 4-way.

#### Colocando um bloco na cache

* O conjunto é determinado pelos bits de índice derivados do endereço do bloco de memória.
* O bloco de memória é colocado em uma linha de cache disponível no set identificado, e a tag é colocada no campo de tag associado com a linha. Se todas as linhas de cache no conjunto estão ocupadas, então os dados novos substituem o bloco identificado conforme a política de substituição.

#### Procurando uma palavra na cache

* O conjunto é determinado pelos bits de índice derivados do endereço do bloco de memória.
* Os bits de tag são comparados com as tags de todas as linhas de cache presentes no set. Se a tag corresponde à qualquer linha de cache, ocorre um acerto de cache (cache hit) e a linha apropriada é retornada. Se a tag não corresponde à qualquer linha, ocorre um erro de cache (cache miss) e os dados são requisitados do próximo nível na hierarquia de memória.

#### Vantagens

* Essa política de cache é uma troca entre as políticas de mapeamento direto e totalmente associativa.
* Oferece a flexibilidade de usar algoritmos de substituição caso haja erro de cache.

#### Desvantagem

* Essa política não usará efetivamente todas as linhas de cache disponíveis e sofre de erro de conflito (conflict miss).

### Algoritmos de substituição de dados

Ai podemos nos perguntar. Mas e quando o cache encher? É aqui que entra o papel dos algoritmos de substituição. Eles tem a função de definir quais linhas com informações atualmente armazenadas vão ser retiradas para dar lugar a uma novas linhas com informações.
Alguns algoritmos são citados abaixo:
Least Recently Used (LRU): Este algoritmo escolhe a linha que esta a mais tempo sem uso pela CPU e substitui pela nova linha.
First Input, First Output (FIFO): FIFO se resume a uma fila qualquer. Um exemplo prático seria uma fila de banco, o primeiro a entrar será o primeiro a ser atendido. No caso da cache, a linha que a mais tempos esta armazenada na cache sera substituída, independentemente se a CPU estiver usando ou não.
Least Frequently Used (LFU): O algoritmo escolhe a linha de acordo com a sua referência, ou seja, a linha que tiver menos acessos por parte da CPU vai ser a escolhida para substituição.

## Modelos de cache

Estes modelos consideram uma hierarquia de memória que possua cache de dados L1 com mapeamento direto.

### Cache de Vítimas

A cache vítima ou CV é uma pequena cache, localizada entre a L1 e os níveis inferiores da cache, usado para armazenar blocos/linhas que foram "expulsos" da cache principal durante a substituição. O cache de vítima geralmente é totalmente associativo e destina-se a reduzir o número de erros de conflito. Na verdade, apenas uma pequena fração dos acessos memória do programa exigem alta associatividade. O cache de vítima explora essa propriedade fornecendo alta associatividade para apenas esses acessos. A política de troca de blocos na CV é LRU. Foi introduzida por Norman Jouppi na década de 90.

### Stream Buffer

Stream Buffer (SB) é uma simples estrutura dentro da cache, que faz buscas para a cache antecipadamente. Esta estrutura reduz o numero de faltas compulsórias. Esta falta ocorre quando um bloco foi pela primeira vez referenciado pela CPU. Isso porque quando ocorre esta falta, o SB pega o endereço desta referência e busca os blocos subsequentes e armazena em uma fila, enquanto a fila não encher, a busca continua.
Em uma requisição da CPU, a referência requisitada é buscada tanto na cache como na SB. Caso ocorra um acerto na fila da SB, o bloco/linha é entregue pra CPU e armazenado na cache. Se ocorrer uma falta na fila e na cache também, os blocos que estão na fila são "expulsos" e o processo de busca retorna a partir do endereço da referência que ocorreu a falta.

## Cache em níveis

Com a evolução na velocidade dos dispositivos, em particular nos processadores, o cache foi dividido em níveis, já que a demanda de velocidade a memória é tão grande que são necessários caches grandes com velocidades altíssimas de transferência e baixas latências. Sendo muito difícil e caro construir memórias caches com essas características, elas são construídas em níveis que se diferem na relação tamanho X desempenho.

### Cache L1

Uma pequena porção de memória estática. Ela pode estar dentro do chip da CPU ou fora dele, existe um ganho de velocidade mais desejável com a cache dentro do chip, pois a comunicação ocorre melhor dentro do chip do que entre chips, o que vem fazendo, atualmente, os chips conterem essa pequena parte da cache (L1) dentro do chip. Mas não termina por aí, para intercalar essas duas partes (dentro e fora), ela foi dividida em 2 níveis: a parte dentro do chip (L1) e a parte de fora do chip (L2).
Em alguns tipos de processador, como o Pentium 2, o L1 é dividido em dois níveis: dados e instruções (que "dizem" o que fazer com os dados). O primeiro processador da Intel a ter o cache L1 foi o i486 com 8KB. Geralmente tem entre 16KB e 128KB; hoje já encontramos processadores com até 16MB de cache.

### Cache L2

Possuindo o Cache L1 um tamanho reduzido e não apresentando uma solução ideal, foi desenvolvido o cache L2, que contém muito mais memória que o cache L1. Ela é mais um caminho para que a informação requisitada não tenha que ser procurada na lenta memória principal. Alguns processadores colocam esse cache fora do processador, por questões econômicas, pois um cache grande implica num custo grande, mas há exceções, como no Pentium II, por exemplo, cujas caches L1 e L2 estão no mesmo cartucho que está o processador. A memória cache L2 é, sobretudo, um dos elementos essenciais para um bom rendimento do processador mesmo que tenha um clock baixo. Um exemplo prático é o caso do Intel Itanium 9152M (para servidores) que tem apenas 1.6 GHz de clock interno e ganha de longe do atual Intel Extreme, pelo fato de possuir uma memória cache de 24MB. Quanto mais alto é o clock do processador, mais este aquece e mais instável se torna. Os processadores Intel Celeron tem um fraco desempenho por possuir menos memória cache L2. Um Pentium M 730 de 1.6 GHz de clock interno, 533 MHz FSB e 2 MB de cache L2, tem rendimento semelhante a um Intel Pentium 4 2.4 GHz, aquece muito menos e torna-se muito mais estável e bem mais rentável do que o Intel Celeron M 440 de 1.86 GHz de clock interno, 533 MHz FSB e 1 MB de cache L2.

### Cache L3

Terceiro nível de cache de memória. Inicialmente utilizado pelo AMD K6-III (por apresentar o cache L2 integrado ao seu núcleo) utilizava o cache externo presente na placa-mãe como uma memória de cache adicional. Ainda é um tipo de cache raro devido à complexidade dos processadores atuais, com suas áreas chegando a milhões de transístores por micrómetros ou nanómetros de área. Ela será muito útil, é possível a necessidade futura de níveis ainda mais elevados de cache, como L4 e assim por diante.

## Smart Cache

Smart Cache é um método de cache de nível 2 ou nível 3 para núcleos de execução múltipla, desenvolvido pela Intel. O Smart Cache compartilha a memória cache real entre os núcleos de um processador multi-core. Em comparação com um cache per-core dedicado, a taxa geral de falta de cache diminui quando nem todos os núcleos precisam de partes iguais do espaço do cache. Conseqüentemente, um único núcleo pode usar o cache de nível 2 ou nível 3, se os outros núcleos estiverem inativos. Além disso, o cache compartilhado torna mais rápido a partilha de memória entre diferentes núcleos de execução.

## Caches unificadas/Caches separadas

Quando o nível L1 da cache começou a aparecer dentro do chip da CPU, apenas uma cache inteira era usada para armazenar dados e instruções, porem tornou-se comum separar a cache em duas partes, 1 dedicada a armazenar dados e a outra dedicada a instruções. Assim, quando o processador busca um dado, ele busca na cache de dados, e quando busca uma instrução, ele busca na cache de instrução.
Ate um certo tamanho, a vantagem fica com a cache unificada, pois a cache tende a equilibrar as buscas por instruções dados, ou seja, se o processador tende a buscar mais instruções, a cache vai armazenar mais instruções. A mesma coisa acontece se o processador busca mais dados. Além disso, somente uma cache precisa ser projetada e implementada.
Mas o futuro tende a continuar com a cache separada, principalmente em computadores superescalares por ex. o PowerPC. Pois esses processadores escalares, executam instruções paralelas e fazem a pré-busca de instruções futuras previstas. Na cache separada o processador busca antecipadamente as instruções e guarda em um buffer com instruções a serem armazenadas. A cache separada ainda não precisa de políticas de escrita, e tem barramentos independentes, onde cada cache se liga ao CPU.

## Caches inclusivos e exclusivos

Caches Multi-level introduzem novos aspectos na sua implementação. Por exemplo, em alguns processadores, todos os dados no cache L1 devem também estar em algum lugar no cache L2. Estes caches são estritamente chamados de inclusivos. Outros processadores (como o AMD Athlon) têm caches exclusivos — os dados podem estar no cache L1 ou L2, nunca em ambos. Ainda outros processadores (como o Pentium II, III, e 4 de Intel), não requerem que os dados no cache L1 residam também no cache L2, embora possam frequentemente fazê-lo. Não há nenhum nome universal aceitado para esta política intermediária, embora o termo inclusivo seja usado.
A vantagem de caches exclusivos é que são capazes de armazenarem mais dados. Esta vantagem é maior quando o cache L1 exclusivo é de tamanho próximo ao cache L2, e diminui se o cache L2 for muitas vezes maior do que o cache L1. Quando o L1 falha e o L2 acerta acesso, a linha correta do cache L2 é trocada com uma linha no L1. Esta troca é um problema, uma vez que a quantidade de tempo para tal troca ser realizada é relativamente alta.
Uma das vantagens de caches estritamente inclusivos é que quando os dispositivos externos ou outros processadores em um sistema multiprocessado desejam remover uma linha do cache do processador, necessitam somente mandar o processador verificar o cache L2. Nas hierarquias de cache exclusiva, o cache L1 deve ser verificado também.
Uma outra vantagem de caches inclusivos é que um cache maior pode usar linhas maiores do cache, que reduz o tamanho das Tags do cache L2. (Os caches exclusivos requerem ambos os caches teres linhas do mesmo tamanho, de modo que as linhas do cache possam ser trocadas em uma falha no L1 e um acerto no L2).
Técnicas de escrita de dados do cache

## Política de escrita

Quando a CPU necessita fazer uma operação de escrita na memória, esta ocorre diretamente na cache. Mas como a cache não é uma memória principal, em algum momento a MP precisa ser atualizada, para manter a integridade. Isso deve acontecer, pois quando uma linha vai ser substituída na cache, antes de isso acontecer, é preciso verificar se essa linha não foi alterada na cache e também não foi alterada na MP. Caso ela tenha sido alterada em algum dos dois casos, isto significa que a linha da cache esta diferente da linha da MP. Isto não pode acontecer, pois a MP precisa estar tão mantida corretamente quanto a cache.
Hoje são encontradas algumas políticas de escritas que resolvem este problema, cada uma com suas vantagens e desvantagens.

### Write-Back Cache

Usando esta técnica a CPU escreve dados diretamente no cache, cabendo ao sistema a escrita posterior da informação na memória principal. Como resultado, o CPU fica livre mais rapidamente para executar outras operações. Em contrapartida, a latência do controlador pode induzir problemas de consistência de dados na memória principal, em sistemas multiprocessados com memória compartilhada. Esses problemas são tratados por protocolos de consistência do cache.
Exemplo:
A escrita de um endereço é feita inicialmente numa linha do cache, e somente no cache. Quando mais tarde algum novo endereço precisar desta linha do cache, estando esta já ocupada, então o endereço inicial é guardado na memória e o novo endereço ocupa-lhe o lugar na respectiva linha do cache.
Para reduzir a frequência de escrita de blocos de endereços na memória aquando da substituição é usado um "dirty bit", este é um bit de estado (atualização), ou seja, quando o endereço é instanciado inicialmente numa linha do cache, estando essa linha vazia, o valor inicial é implicitamente '0', quando o bloco do endereço é modificado (quando ocorre uma substituição) o valor inicial passa a '1' e diz-se que o bloco do endereço está "dirty".
Vantagens
* a escrita ocorre à velocidade do cache;
* escritas múltiplas de um endereço requerem apenas uma escrita na memória;
* consome menos largura de banda.
Desvantagens
* difícil de implementar;
* nem sempre existe consistência entre os dados existentes no cache e na memória;
* leituras de blocos de endereços no cache podem resultar em escritas de blocos de endereços "dirty" na memória.

### Write-Through Cache

É a técnica mais simples usada. As operações de escrita são feitas tanto na memória Principal como na cache, garantindo que a memória principal esteja sempre valida. Este tipo de política providencia pior desempenho do que Write-Back Cache, pois ela gera um grande trafego na memória principal, podendo formar gargalos, mas é mais simples de implementar e tem a vantagem da consistência interna, porque o cache nunca está dessincronizada com a memória como acontece com a técnica Write-Back Cache.
Vantagens
* fácil de implementar;
* um "cache-miss" nunca resulta em escritas na memória;
* a memória tem sempre a informação mais recente.
Desvantagens
* a escrita é lenta;
* cada escrita necessita de um acesso à memória;
* consequentemente usa mais largura de banda da memória;
* alto uso do barramento da memória.

## Técnicas de "Write Miss"
### Write Allocate

O bloco de endereço é carregado na ocorrência seguindo-se uma acção de "write hit". O "Write Allocate" é usado com frequência em caches de "Write Back".

### No Write Allocate

O bloco de endereço é diretamente modificado na memória, não é carregado no cache. O "No Write Allocate" é usado frequentemente em caches de "Write Through".