Ao tentar compreender sistemas complexos, você pode aprender muito ao destrinchar as abstrações e olhar para seus níveis mais baixos. Com esse espírito, olharemos para memória e portas I/O em seu nível mais simples e fundamental: a interface entre o processador e o barramento. Esses detalhes são suporte para tópicos de níveis mais altos, como sincronização de threads e a necessidade do Core i7. Além disso, como sou programador, eu ignoro coisas com as quais as pessoas de engenharia eletrônica se importam. Aqui está nosso amigo, o Core 2, novamente:
Um processador Core 2 tem 775 pinos, e metade deles somente fornece força e não carrega dados. Uma vez que você agrupa os pinos por funcionalidade, a interface física do processador é surpreendentemente simples.
O diagrama mostra os pinos chave envolvidos em uma memória ou operação de porta I/O: address lines, data pins e request pins. Essas operações acontecem no contexto de uma transação no FSB.Transações FSB passam por 5 fases: arbitragem, requisição, snoop, resposta e dados. Através dessas fases, diferentes papeis são executados pelos componentes no FSB, que são chamados de agentes. Normalmente, os agentes são todos os processadores mais o northbridge.
Nós somente olharemos para a fase de requisição neste artigo, no qual a saída de dois pacotes é feita pelo agente de requisição, que geralmente é um processador. Aqui estão os principais bits do primeiro pacote, que é a saída do endereço e dos pinos requisitados:

As address lines iniciam a saída do endereço da memória física da transação. Nós temos 33 bits, mas eles são interpretados como bits 35-3 de um endereço no qual bits 2-0 são zero. Assim, temos um endereço de 36-bit, alinhado a 8 bytes, para um total de 64 GB de memória física endereçável. Esse tem sido o caso desde o Pentium Pro. Os request pins especificam que tipo de transação está sendo iniciada; nas requisições I/O, os address pins especificam uma porta I/O em vez de um endereço de memória. Depois de o primeiro pacote ter saído, os mesmos pinos transmitem um segundo pacote no ciclo do barramento subsequente:

Os sinais de atributos são interessantes: eles refletem cinco tipos de comportamentos de cache de memória disponíveis em processadores Intel. Ao inserir essa informação no FSB, o agente de requisição permite que outros processadores saibam como essa transação afeta seus caches, e como o controlador de memória (northbridge) deveria se comportar. O processador determina o tipo de uma determinada região de memória ao olhar para as tabelas de página, que são mantidas pelo kernel.
Normalmente, os kernels tratam todas a memória RAM como write-back, que produz melhor desempenho. No modo write-back, a unidade de acesso é o cache line, 64 bytes no Core 2. Se um programa lê um único byte na memória, o processador carrega toda a cache line que contém esse byte nos caches L1 e L2.
Quando um programa escreve na memória, o processador somente modifica a linha no cache, mas não atualiza a memória principal. Depois, quando se torna necessário postar a linha modificada no barramento, toda a cache line é escrita de uma vez. Assim, a maior parte dos pedidos tem 11 em seu campo de comprimento, para 64 bytes. Aqui está um exemplo de leitura no qual os dados não estão nos caches.

Alguma parte do alcance da memória física em um computador Intel é mapeado para dispositivos como discos rígidos e placas de rede em vez da memória RAM de fato. Isso permite aos drivers se comunicarem com seus dispositivos ao escreverem para memória e lendo a partir dela. O kernel marca essas regiões de memória como “não cacheáveis” nas tabelas de páginas. Acessos a regiões de memória “não cacheáveis” são reproduzidos no barramento exatamente como requisitados por um programa ou driver. Assim, é possível ler ou escrever bytes únicos, palavras, e assim por diante. Isso é feito através da habilitação da máscara para bytes no pacote B acima.
As premissas discutidas aqui têm muitas implicações. Por exemplo:
- Aplicações sensíveis a desempenho deveriam tentar empacotar os dados que são acessados juntos na mesma cache line. Uma vez que a cache line é carregada, as próximas leituras são muito mais rápidas e acessos extras à RAM são evitados.
- Qualquer acesso à memória que cai dentro de uma única cache line é garantidamente atômica (pressupondo uma memória write-back). Tal acesso é servido pelo processador do cache da L1, e o dado é lido ou escrito de uma vez; ele não pode ser afetado pela metade por outros processadores ou threads. As operações de 32-bit e 64-bit, em particular, que não ultrapassam os limites da cache line, são atômicas.
- O barramento frontal é compartilhado por todos os agentes, que devem arbitrar pela propriedade antes de começarem a transação. Além disso, todos os agentes devem ouvir todas as transações para manter a coerência do cache. Assim, a contenção do bus se torna um problema sério na medida em que mais cores e processadores são adicionados aos computadores Intel. O Core i7 resolve esse problema tendo processadores diretamente ligado à memória e se comunicando diretamente a ela ao invés da forma antiga, usando broadcast.
Esses são os destaques dos pedidos de memória física; o barramento irá surgir novamente em conexão com fechamento, multi-threading, e coerência do cache. A primeira vez em que eu vi descrições de pacotes FSB, eu tive um grande momento “Uau”. Então, espero que alguém por aí tenham algum benefício.
?
Texto original disponível em http://duartes.org/gustavo/blog/post/getting-physical-with-memory








