Alinhamento na memória

Na computação , as restrições de alinhamento de memória se limitam a certos múltiplos de endereços de memória , onde certos dados e instruções de máquina podem ser armazenados. Além disso, as otimizações de alinhamento de memória permitem que você influencie a velocidade de execução de um programa apenas escolhendo os endereços corretos.

Princípio

Para aumentar seu desempenho, os processadores são frequentemente conectados à RAM por um barramento de dados maior do que a granularidade de seu endereçamento: por exemplo, um processador é capaz de endereçar bytes individualmente (8 bits ), conectado à memória por um 4 bytes ( Barramento de 32 bits). Se um dado de 4 bytes não estiver em um endereço divisível por 4, então, dependendo do modelo do processador, haverá:

A regra geral aplicável para que um dado fique bem alinhado é que ele está localizado em um endereço divisível por seu tamanho. Assim, um item de dados ocupando um único byte está sempre bem alinhado, um dado de dois bytes está bem alinhado se estiver em um endereço par, um dado de 4 bytes está bem alinhado se estiver em um endereço divisível por 4, etc. No entanto, a restrição de alinhamento não excede o hardware subjacente.

As restrições de alinhamento na memória dependem da arquitetura do processador . Otimizar o alinhamento é mais sutil, pois pode depender da memória cache do processador , paginação de memória virtual e outras características de acesso à memória. Alguns compiladores permitem que você influencie o alinhamento dos dados.

Conveniente

Instruções

Os processadores RISC normalmente têm apenas um tamanho de instrução de máquina, e essas instruções devem ser alinhadas corretamente. Em contraste, os processadores CISC têm instruções de tamanhos variados. Portanto, às vezes pode ser bom para o desempenho inserir uma nopoperação ineficaz (frequentemente chamada ) para que as instruções subsequentes fiquem melhor alinhadas.

Dados

Quando dados de tamanhos diferentes são armazenados na memória um após o outro, pode ser útil, ou mesmo necessário, deixar lacunas entre eles para que fiquem todos devidamente alinhados. Isso pode ser observado em particular na pilha de execução e nos tipos de dados compostos.

Tipo de dados composto em C

Considere dois tipos de dados compostos em linguagem C , considerando um equipamento com um barramento de endereçamento de 64 bits (8 bytes):

struct no_align { char c; double d; int i; char c2[3]; }; struct align { double d; int i; char c2[3]; char c; };

Ambas as estruturas contêm os mesmos membros. Podemos, portanto, deduzir que eles têm o mesmo tamanho. Assim, supondo que:

  • o tipo charé 1 byte;
  • o tipo inté 4 bytes;
  • o tipo doubleé de 8 bytes.

o tamanho total seria 1 + 8 + 4 + 3 × 1 = 16 bytes.

No entanto, se exibirmos o tamanho com a instrução, printf("%zu %zu\n", sizeof(struct no_align), sizeof(struct align));temos uma boa chance de obter 24 e 16 bytes. Na verdade, os membros da estrutura alignestão bem alinhados, mas não os de no_align. O compilador adiciona os chamados bytes de preenchimento para respeitar o alinhamento. Quando compilado, no_alignfica assim:

struct no_align_compile { char c; char __pad1[7]; double d; int i; char c2[3]; char __pad2; };

Observe que __pad1permite diniciar em um endereço múltiplo de 8 e __pad2completa a estrutura para chegar a 24, um múltiplo de 8.

Opções de compilação

Com o GCC , a opção -Wpaddedpermite saber se uma estrutura precisa de preenchimento para ser alinhada. Aqui estão as mensagens obtidas durante a compilação struct no_align :

Warning padding struct to align 'd' Warning padding struct size to alignment boundary

Bibliografia

  • (in) Manual do AC de referência , 5 ª  edição, Samuel P. Harbison III, Guy L. Aço Jr., Prentice Hall, 2002
    • §6.1.3 Restrições de alinhamento
    • §5.6.7 Tamanhos de Estruturas
  • (pt) GCC 4.9.2 Manual , §3.8 Opções para solicitar ou suprimir avisos