É certo que eu não entendo. Digamos que você tenha uma memória com uma palavra de duração de 1 byte. Por que você não pode acessar uma variável de 4 bytes de comprimento em um único acesso à memória em um endereço não alinhado (ou seja, não divisível por 4), como é o caso dos endereços alinhados?
195
Respostas:
É uma limitação de muitos processadores subjacentes. Geralmente, isso pode ser resolvido com quatro buscas ineficientes de um byte, em vez de uma busca eficiente de palavras, mas muitos especificadores de idioma decidiram que seria mais fácil apenas proibi-los e forçar o alinhamento de tudo.
Há muito mais informações neste link que o OP descobriu.
fonte
O subsistema de memória em um processador moderno é restrito ao acesso à memória na granularidade e alinhamento do tamanho da palavra; esse é o caso por várias razões.
Rapidez
Os processadores modernos têm vários níveis de memória cache nos quais os dados devem ser extraídos; o suporte a leituras de byte único faria com que a taxa de transferência do subsistema de memória estivesse fortemente ligada à taxa de transferência da unidade de execução (também conhecida como limite da CPU); tudo isso lembra como o modo PIO foi superado pelo DMA por muitos dos mesmos motivos nos discos rígidos.
A CPU sempre lê em seu tamanho de palavra (4 bytes em um processador de 32 bits); portanto, quando você acessa um endereço desalinhado - em um processador que a suporta -, o processador lê várias palavras. A CPU lerá cada palavra de memória que o endereço solicitado se encontra. Isso causa uma amplificação de até 2X o número de transações de memória necessárias para acessar os dados solicitados.
Por esse motivo, pode ser muito mais lento ler dois bytes que quatro. Por exemplo, digamos que você tenha uma estrutura na memória parecida com esta:
Em um processador de 32 bits, provavelmente seria alinhado como mostrado aqui:
O processador pode ler cada um desses membros em uma transação.
Digamos que você tenha uma versão compactada da estrutura, talvez da rede em que foi compactada para obter eficiência de transmissão; pode ser algo como isto:
Ler o primeiro byte será o mesmo.
Quando você solicita que o processador forneça 16 bits de 0x0005, ele precisará ler uma palavra de 0x0004 e deslocar para a esquerda 1 byte para colocá-lo em um registro de 16 bits; algum trabalho extra, mas a maioria pode lidar com isso em um ciclo.
Quando você pede 32 bits de 0x0001, obtém uma amplificação de 2X. O processador lerá de 0x0000 no registro de resultados e mudará 1 byte para a esquerda, depois lerá novamente de 0x0004 para um registro temporário, mudará para a direita 3 bytes e depois
OR
com o registro de resultados.Alcance
Para qualquer espaço de endereço especificado, se a arquitetura puder assumir que os 2 LSBs são sempre 0 (por exemplo, máquinas de 32 bits), poderá acessar 4 vezes mais memória (os 2 bits salvos podem representar 4 estados distintos) ou a mesma quantidade de memória com 2 bits para algo como bandeiras. Desativar os 2 LSBs de um endereço daria um alinhamento de 4 bytes; também conhecido como passo de 4 bytes. Cada vez que um endereço é incrementado, ele efetivamente incrementa o bit 2, e não o 0, ou seja, os últimos 2 bits sempre continuarão sendo
00
.Isso pode até afetar o design físico do sistema. Se o barramento de endereço precisar de 2 bits a menos, pode haver 2 pinos a menos na CPU e 2 traços a menos na placa de circuito.
Atomicidade
A CPU pode operar atomicamente em uma palavra de memória alinhada, o que significa que nenhuma outra instrução pode interromper essa operação. Isso é fundamental para a operação correta de muitas estruturas de dados sem bloqueio e outros paradigmas de simultaneidade .
Conclusão
O sistema de memória de um processador é um pouco mais complexo e envolvido do que o descrito aqui; uma discussão sobre como um processador x86 realmente aborda a memória pode ajudar (muitos processadores funcionam de maneira semelhante).
Há muitos outros benefícios em aderir ao alinhamento de memória que você pode ler neste artigo da IBM .
O uso principal de um computador é transformar dados. As arquiteturas e tecnologias modernas de memória foram otimizadas ao longo de décadas para facilitar a obtenção de mais dados, entrada, saída e entre mais e mais unidades de execução mais rápidas - de uma maneira altamente confiável.
Bônus: caches
Outro alinhamento por desempenho que eu aludi anteriormente é o alinhamento em linhas de cache que são (por exemplo, em algumas CPUs) 64B.
Para obter mais informações sobre quanto desempenho pode ser obtido aproveitando os caches, consulte a Galeria de efeitos de cache do processador ; desta pergunta sobre tamanhos de linha de cache
fonte
você pode com alguns processadores ( o nehalem pode fazer isso ), mas anteriormente todo o acesso à memória era alinhado em uma linha de 64 bits (ou 32 bits), porque o barramento tem 64 bits de largura, era necessário buscar 64 bits por vez , e foi significativamente mais fácil buscá-los em 'pedaços' alinhados de 64 bits.
Portanto, se você quisesse obter um único byte, buscou o pedaço de 64 bits e mascarou os bits que não queria. Fácil e rápido se o seu byte estava na extremidade certa, mas se estivesse no meio desse bloco de 64 bits, você teria que mascarar os bits indesejados e depois transferir os dados para o local certo. Pior, se você quisesse uma variável de 2 bytes, mas que fosse dividida em 2 partes, seria necessário o dobro dos acessos à memória necessários.
Assim, como todos pensam que a memória é barata, eles apenas fizeram o compilador alinhar os dados nos tamanhos dos fragmentos do processador, para que seu código funcione mais rápido e com mais eficiência, com o custo da memória desperdiçada.
fonte
Fundamentalmente, o motivo é que o barramento de memória possui um comprimento específico muito, muito menor que o tamanho da memória.
Portanto, a CPU lê fora do cache L1 no chip, que costuma ter 32 KB atualmente. Mas o barramento de memória que conecta o cache L1 à CPU terá uma largura muito menor do tamanho da linha de cache. Isso será da ordem de 128 bits .
Assim:
Os acessos desalinhados ocasionalmente se sobrepõem a duas linhas de cache, e isso exigirá uma leitura totalmente nova do cache para obter os dados. Pode até faltar todo o caminho para a DRAM.
Além disso, parte da CPU terá que ficar de cabeça para montar um único objeto dessas duas linhas de cache diferentes, cada uma com uma parte dos dados. Em uma linha, ele estará nos bits de ordem muito alta, na outra, nos bits de ordem muito baixa.
Haverá hardware dedicado totalmente integrado ao pipeline que manipula objetos alinhados nos bits necessários do barramento de dados da CPU, mas esse hardware pode estar ausente para objetos desalinhados, porque provavelmente faz mais sentido usar esses transistores para acelerar a otimização correta programas.
De qualquer forma, a segunda leitura de memória que às vezes é necessária desaceleraria o pipeline, independentemente de quanto hardware de propósito especial fosse (hipoteticamente e tolamente) dedicado a corrigir operações de memória desalinhadas.
fonte
@joshperry deu uma excelente resposta a esta pergunta. Além de sua resposta, tenho alguns números que mostram graficamente os efeitos que foram descritos, especialmente a amplificação 2X. Aqui está um link para uma planilha do Google mostrando como são os efeitos de diferentes alinhamentos de palavras. Além disso, aqui está um link para uma essência do Github com o código para o teste. O código do teste é adaptado do artigo escrito por Jonathan Rentzsch ao qual @joshperry referenciou. Os testes foram executados em um Macbook Pro com um processador Intel Core i7 de 64 bits e núcleo quádruplo de 2,8 GHz e 16 GB de RAM.
fonte
x
ey
coordenadas?Se um sistema com memória endereçável em bytes tiver um barramento de memória de 32 bits, significa que existem efetivamente quatro sistemas de memória em bytes que estão todos conectados para ler ou gravar o mesmo endereço. Uma leitura alinhada de 32 bits exigirá informações armazenadas no mesmo endereço nos quatro sistemas de memória, para que todos os sistemas possam fornecer dados simultaneamente. Uma leitura desalinhada de 32 bits exigiria que alguns sistemas de memória retornassem dados de um endereço e outros retornassem dados do próximo endereço superior. Embora existam alguns sistemas de memória otimizados para atender a essas solicitações (além do endereço, eles efetivamente possuem um sinal "mais um" que os leva a usar um endereço mais alto do que o especificado), esse recurso adiciona um custo considerável e complexidade para um sistema de memória;
fonte
Se você tiver um barramento de dados de 32 bits, as linhas de endereço do barramento de endereço conectadas à memória serão iniciadas em A 2 , de modo que apenas os endereços de 32 bits alinhados pode ser acessada em um único ciclo de ônibus.
Portanto, se uma palavra ultrapassar um limite de alinhamento de endereço - por exemplo, A 0 para dados de 16/32 bits ou A 1 para 32 bits de dados são não zero, dois ciclos do bus são necessários para obter os dados.
Algumas arquiteturas / conjuntos de instruções não suportam acesso não alinhado e geram uma exceção em tais tentativas; portanto, o código de acesso não alinhado gerado pelo compilador requer não apenas ciclos adicionais de barramento, mas instruções adicionais, tornando-o ainda menos eficiente.
fonte
No PowerPC, você pode carregar um número inteiro de um endereço ímpar sem problemas.
Sparc e I86 e (acho) Itatnium levantam exceções de hardware quando você tenta isso.
Uma carga de 32 bits versus quatro cargas de 8 bits não fará muita diferença na maioria dos processadores modernos. Se os dados já estão no cache ou não, terá um efeito muito maior.
fonte