Como um barramento de memória compartilhada é usado para leituras e gravações de dados compartilhados entre threads de maneira segura e correta?

1

Gostaria de entender em alto nível como o barramento de memória compartilhada lida com várias leituras e gravações simultâneas de dados compartilhados de vários segmentos em execução em vários processadores?

P.S: Eu não preciso dos detalhes, porque obviamente será específico da implementação. Eu só preciso de uma visão geral de alto nível do que acontece nos bastidores.

    
por Geek 02.09.2013 / 05:59

2 respostas

1

Um "bus" é um conjunto de fios entre componentes, em vez de um componente em si. Portanto, a fiação entre uma CPU e sua memória é chamada de barramento de memória; a fiação para as placas de expansão é o barramento PCI, etc.

É possível ter vários componentes acionando um barramento, embora apenas um possa acioná-lo de uma só vez e seus sinais sejam entregues a todos os outros componentes no barramento. O componente que controla o acesso ao barramento é chamado de barramento mestre . Pode ser possível alterar qual componente é o mestre do barramento por arbitragem .

Em um sistema multi-core, a consistência do cache é importante. Assim, quando um núcleo grava no barramento de memória compartilhada, outros núcleos irão espionar o barramento (examine a gravação, mesmo que esteja indo de outro núcleo para a memória). Se a gravação for para um local armazenado em cache por esse núcleo, o núcleo removerá ou substituirá sua entrada de cache. Dessa forma, não tem informações obsoletas.

    
por 02.09.2013 / 12:00
1

Um módulo de memória (um DIMM) só pode fazer uma coisa de cada vez: uma leitura ou uma gravação. Isso é determinado pelo protocolo no conector de borda do DIMM; uma vez que você envia um comando de leitura ou escrita para um DIMM, ele não pode nem mesmo "ouvir" outro até que o comando anterior esteja completo.

Todos os DIMMs em um barramento de memória comum terão coletivamente essa restrição um por vez. Mas em muitas plataformas de PC existem dois ou três canais de memória , e toda a RAM em um canal pode coletivamente fazer apenas uma coisa de cada vez.

Em máquinas NUMA (aquelas com múltiplos soquetes de CPU e memória "privada" para cada soquete) tudo isso é multiplicado por nCPUs. isto é, cada CPU pode estar acessando sua memória local, independentemente do que a outra CPU esteja fazendo com a sua sua memória. No entanto, todos os processadores ainda podem acessar toda a memória RAM, só demora um pouco mais se eles tiverem que passar por outra CPU.

Fundamentalmente, cabe ao código dos aplicativos implementar quaisquer requisitos de serialização que eles tenham para acesso a dados compartilhados. Isso é feito com a ajuda do sistema operacional, que fornecerá vários objetos e funções de sincronização para os aplicativos usarem. Esses objetos têm nomes como semáforos (nome emprestado do sinal da ferrovia), exclusões mútuas (abreviação de "exclusão mútua"), etc. Dependendo do sistema operacional, eles podem implementar um por vez, n-a-vez, gravação exclusiva versus leitura compartilhada, etc., semântica. Estas funções normalmente envolvem "espera" ou "bloqueio": Um thread tenta, e. adquirir um mutex que, por design, "protege" um recurso compartilhado. Se o mutex já pertence a algum outro segmento, então o segundo (e _n_th) segmento de solicitação é bloqueado, ou seja, aguarda e não retorna da chamada de aquisição, até que o proprietário anterior o libere.

Cabe aos aplicativos usar essas técnicas quando necessário; o sistema operativo não tem como exigir que, e. você tem que possuir um mutex particular antes de acessar os dados que você pretendia que o mutex protegesse. Esta é uma área de design de programa que pode ser muito difícil para ambos acertarem e terem alto desempenho.

Subsistemas de nível superior, como bancos de dados, têm essa codificação integrada para os dados que gerenciam e apresentam uma interface para o programador que "fala" em termos de elementos de banco de dados, em vez de objetos de sincronização: O programador invocaria funções para bloquear uma linha da tabela ou uma célula individual ou um conjunto de linhas, ou talvez uma tabela inteira, enquanto executa atualizações. Abaixo do mecanismo do banco de dados, serão utilizadas as instalações do sistema operacional, conforme descrito anteriormente.

Internamente, o sistema operacional geralmente implementa essas funções de sincronização com o auxílio de algum tipo de operação de teste e modificação atômica implementada no subsistema de memória. Por "atômica" quero dizer que, uma vez iniciada, a operação é garantida para ser concluída antes que qualquer outra operação atômica possa começar na memória afetada. Um exemplo comumente usado no Windows é a instrução "interlocked compare-and-exchange". Na verdade, x86 / x64 fornece uma série de instruções, trabalhando em vários tamanhos de dados.

Existem métodos que permitem acesso serializado seguro a dados compartilhados sem o uso de tais técnicas, mas eles funcionam apenas para alguns casos especiais (por exemplo, "apenas um leitor e apenas um gravador") ou para determinados tipos de dados.

    
por 14.09.2015 / 12:03

Tags