Pergunta

É certo que eu não entendo. Digamos que você tenha uma memória com uma palavra de memória de comprimento de 1 byte. Por que você não pode acessar uma variável longo de 4 bytes em um único acesso de memória em um endereço desalinhadas (i. Não é divisível por 4), como é o caso com endereços alinhados?

Foi útil?

Solução

É uma limitação de muitos processadores subjacentes. Ele normalmente pode ser contornado fazendo 4 ineficientes buscas de byte único, em vez de uma palavra eficiente buscar, mas muitos especificadores de linguagem decidiram que seria mais fácil apenas para proibir eles e força de tudo para estar alinhados.

Há muito mais informação no este link que o OP descoberto.

Outras dicas

O subsistema de memória em um processador moderno é restrito a acessar a memória na granularidade e alinhamento do seu tamanho palavra; este é o caso para uma série de razões.

Speed ??

Os processadores modernos têm vários níveis de memória cache que os dados devem ser puxados através; apoiar single-byte lê faria a memória subsistema de rendimento fortemente ligada à unidade de execução de transferência (aka vinculado à CPU); tudo isso é uma reminiscência de como PIO foi superado pelo DMA para muitas das mesmas razões em discos rígidos.

A CPU sempre lê em seu tamanho palavra (4 bytes em um processador de 32 bits), então quando você faz um acesso endereço desalinhadas - em um processador que o suporta - o processador vai ler várias palavras. A CPU vai ler cada palavra de memória que seus straddles endereço solicitado. Isso faz com que uma amplificação de até 2x o número de transações de memória necessária para acessar os dados solicitados.

Devido a isso, ele pode muito facilmente ser mais lento para ler dois bytes de quatro. Por exemplo, digamos que você tem uma estrutura na memória que se parece com isso:

struct mystruct {
    char c;  // one byte
    int i;   // four bytes
    short s; // two bytes
}

Em um processador de 32 bits seria mais provável ser alinhados como mostrado aqui:

Struct Layout

O processador pode ler cada um desses membros em uma transação.

dizer que você tinha uma versão compactada da estrutura, talvez a partir da rede onde ele estava lotado para a eficiência de transmissão; que poderia ser algo como isto:

Embalado Struct

A leitura do primeiro byte vai ser o mesmo.

Quando você pergunta o processador para lhe dar 16 bits de 0x0005 terá de ler uma palavra a partir de 0x0004 e deslocamento para a esquerda 1 byte para colocá-lo num registo de 16 bits; algum trabalho extra, mas a maioria pode lidar com isso em um ciclo.

Quando você pedir para 32 bits a partir de 0x0001 você vai ter uma amplificação 2X. O processador vai ler a partir de 0x0000 no registo resultado e deslocamento para a esquerda um byte, em seguida, ler a partir de 0x0004 novamente num registo temporário, deslocamento para a direita 3 bytes, em seguida, OR-lo com o registo de resultados.

Gama

Para qualquer espaço de endereço, se a arquitetura pode assumir que os 2 LSB são sempre 0 (por exemplo, máquinas de 32 bits), então ele pode 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. Tomando os 2 LSB fora de um endereço iria dar-lhe um alinhamento de 4 bytes; também referido como um passo de 4 bytes. Cada vez que um endereço é incrementado é efetivamente incrementando bit 2, não bit 0, ou seja, os últimos 2 bits continuará sempre a ser 00.

Isso pode até afetar o projeto físico do sistema. Se o barramento de endereços precisa de 2 menos bits, pode haver menos 2 pinos da CPU, e menos 2 traços na placa de circuito.

Atomicity

A CPU pode operar em uma palavra alinhada da memória atomicamente, o que significa que nenhuma outra instrução pode interromper essa operação. Isto é fundamental para o correto funcionamento de muitos estruturas de dados livre de bloqueio e outro simultaneidade paradigmas.

Conclusão

O sistema de memória de um processador é um pouco mais complexo e complicado do que o descrito aqui; uma discussão sobre como um processador x86, na verdade, endereços de memória pode ajudar (muitos processadores funcionam de forma semelhante ).

Existem mmais benefícios de aderir ao alinhamento de memória que você pode ler em este artigo IBM .

principal uso de um computador é transformar dados. arquiteturas de memória e tecnologias modernas foram otimizados ao longo de décadas para facilitar a obtenção de mais dados, dentro, fora, e entre os mais e mais rápido unidades em execução uma forma altamente confiável.

Bonus: caches

Outro alinhamento por desempenho que aludido anteriormente é o alinhamento das linhas de cache que são (por exemplo, em alguns CPUs) 64B.

Para mais informações sobre o quanto o desempenho pode ser adquirida através da alavancagem caches, dar uma olhada em Galeria do processador de efeitos Cache ; a partir desta pergunta em cache-linha tamanhos

A compreensão de linhas de cache pode ser importante para certos tipos de otimizações do programa. Por exemplo, o alinhamento dos dados pode determinar se uma operação toca uma ou duas linhas de cache. Como vimos no exemplo acima, isso pode facilmente significar que, no caso desalinhado, a operação será duas vezes mais lento.

Você pode com alguns processadores ( o Nehalem pode fazer este ), mas já todos o acesso à memória foi alinhado em um 64-bit (ou) linha 32-bit, porque o ônibus é de 64 bits de largura, você tinha que ir buscar 64 bits de cada vez, e foi significativamente mais fácil para buscar estes em 'pedaços' alinhados de 64 bits.

Então, se você queria ter um único byte, você pegou o pedaço de 64 bits e, em seguida, mascarado fora os bits que você não quer. Fácil e rápido se o seu byte foi na extremidade direita, mas se ele estava no meio daquele pedaço de 64 bits, você teria que mascarar os bits indesejados e, em seguida, transferir os dados para o lugar certo. Pior ainda, se você queria uma variável de 2 bytes, mas que foi dividido por 2 pedaços, em seguida, que exigia o dobro dos acessos à memória necessários.

Assim, como todo mundo acha que a memória é barato, eles apenas fizeram o align compilador dos dados sobre tamanhos do pedaço do processador para que o seu código é executado mais rápido e de forma mais eficiente com o custo de memória desperdiçada.

No fundo, a razão é porque o barramento de memória tem algum comprimento específico que é muito, muito menor do que o tamanho da memória.

Assim, a CPU lê fora do cache L1 on-chip, que é muitas vezes 32KB estes dias. Mas o barramento de memória que liga o cache L1 para a CPU terá a largura muito menor do tamanho da linha de cache. Este será da ordem de 128 pedaços .

Assim:

262,144 bits - size of memory
    128 bits - size of bus

acessos desalinhados irá ocasionalmente se sobrepõem duas linhas de cache, e isso vai exigir uma inteiramente nova cache de leitura a fim de obter os dados. Ele pode até mesmo perder todo o caminho para o DRAM.

Além disso, uma parte da CPU terá que ficar em sua cabeça para montar um único objeto fora destas duas linhas de cache diferentes que cada um tem um pedaço dos dados. Em uma linha, será nos bits muito alta ordem, no outro, os bits muito baixa ordem.

Haverá hardware dedicado totalmente integrado ao gasoduto que lida com objetos em movimento alinhados para os bits necessários do barramento de dados da CPU, mas tal hardware pode faltar para objetos desalinhados, porque, provavelmente, faz mais sentido usar esses transistores por excesso de velocidade corretamente programas otimizados.

Em qualquer caso, a segunda memória de leitura que às vezes é necessário iria abrandar o gasoduto não importa o quanto de hardware de propósito especial foi (hipoteticamente e tolamente) dedicado a remendar operações de memória desalinhados.

@joshperry deu uma excelente resposta a esta pergunta. Além de sua resposta, eu tenho alguns números que mostram graficamente os efeitos que foram descritos, especialmente a ampliação 2X. Aqui está um link para um Google planilha mostrando o que o efeito de alinhamentos palavra diferente parecido. Além disso, aqui está um link para um Github essência com o código para o teste. O código de teste é uma adaptação do o artigo escrito pelo qual @joshperry Jonathan Rentzsch referenciada. Os testes foram executados em um Macbook Pro com um quad-core de 2,8 GHz Intel Core i7 processador de 64 bits e 16 GB de RAM.

enter descrição da imagem aqui

Se um sistema com memória byte endereçável tem um bus de memória de largura de 32 bits, isso significa que há efetivamente quatro sistemas de memória de largura de bytes que são todos conectados a ler ou escrever o mesmo endereço. Uma leitura de 32 bits alinhados exigirá informações armazenadas no mesmo endereço em todos os quatro sistemas de memória, por isso, todos os sistemas podem fornecer dados simultaneamente. Uma leitura de 32 bits não alinhado exigiria alguns sistemas de memória para retornar dados de um endereço, e alguns para devolver dados a partir do endereço imediatamente superior. Embora existam alguns sistemas de memória que são otimizados para ser capaz de cumprir esses pedidos (para além do seu endereço, eles efetivamente têm um sinal de "mais um" que faz com que usar um endereço de um maior do que o especificado) de tal recurso adiciona um custo considerável ea complexidade de um sistema de memória; a maioria dos sistemas de memória de commodities simplesmente não pode voltar porções de diferentes palavras de 32 bits ao mesmo tempo.

Se você tem um barramento de dados de 32 bits, as linhas de endereço barramento de endereços ligados à memória vai começar a partir de A 2 , portanto, apenas os endereços de 32 bits alinhados pode ser acessada em um único ciclo de ônibus.

Assim, se uma palavra vãos um alinhamento de fronteira endereço - ou seja, A 0 para 16/32 bits de dados ou A 1 para 32 bits de dados não são zero, dois ciclos de ônibus são necessários para obter os dados.

Algumas arquiteturas / conjuntos de instruções não suportam acesso desalinhado e irá gerar uma exceção em tais tentativas, então compilador gerado código de acesso desalinhado requer não apenas ciclos de ônibus adicionais, mas instruções adicionais, tornando ainda menos eficiente.

No PowerPC você pode carregar um número inteiro de um endereço ímpar sem problemas.

Sparc e I86 e (eu acho) exceções de hardware raise Itatnium quando você tentar isso.

Uma carga de 32 bit vs quatro 8 cargas bit não está indo fazer um monte de diferença na maioria dos processadores modernos. Se os dados já em cache ou não é terá um efeito muito maior.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top