Pergunta

Eu posso entender esta exigência para os antigos sistemas PPC RISC e até mesmo para x86-64, mas para o velho x86 tentou-e-verdade? Neste caso, a pilha precisa ser alinhado apenas em limites de 4 bytes. Sim, algumas das instruções MMX / SSE exigem alinhamentos 16 bytes, mas se isso é uma exigência do receptor, então ele deve garantir que os alinhamentos estão corretas. Por que carga todas chamador com este requisito extra? Isso pode realmente causar algumas gotas no desempenho porque cada chamada local deve gerenciar este requisito. Estou faltando alguma coisa?

Update: Depois de mais alguns investigação sobre isso e algumas consultas com alguns colegas internos, eu tenho algumas teorias sobre isso:

  1. A coerência entre a PPC, x86 e x64 versão do OS
  2. Parece que o GCC CodeGen agora consistentemente que um sub esp, xxx e, em seguida, "mov" s os dados para a pilha ao invés de simplesmente fazer uma instrução de "push". Isso poderia realmente ser mais rápido em algum hardware.
  3. Enquanto isto complica os sites de chamada um pouco, há muito pouco extra de sobrecarga ao usar o padrão "cdecl" convenções onde o chamador limpa a pilha.

O problema que tenho com o último item, é que para chamar convenções que contam com o receptor de limpar a pilha, os requisitos acima realmente "uglifies" o codegen. Por exemplo, que algum compilador decidiu implementar um estilo que chama mais rápido baseado em registrar-se para seu próprio uso interno (ou seja, qualquer código que não se destina a ser chamado de outros idiomas ou fontes)? Essa coisa pilha-alinhamento poderia negar alguns dos ganhos de desempenho alcançados pela passagem de alguns parâmetros em registos.

Update: Até agora, as respostas só reais foram consistência, mas para mim isso é um pouco fácil demais de uma resposta. Tenho bem mais de 20 anos de experiência com a arquitetura x86 e se a consistência, não o desempenho, ou algo mais concreto, é realmente a razão, então eu respeitosamente sugerir que é um pouco ingênuo para os desenvolvedores para exigi-lo. Eles estão ignorando quase três décadas de ferramentas e suporte. Especialmente se eles estão esperando fornecedores de ferramentas de forma rápida e facilmente adaptar suas ferramentas para a sua plataforma (talvez não ... ele é Apple ...) sem ter que saltar através de vários aros aparentemente desnecessários.

Eu vou dar a este tópico mais um dia ou menos, em seguida, fechá-lo ...

Relacionados

Foi útil?

Solução

De "Intel®64 e IA-32 arquiteturas Otimização Referência Manual", seção 4.4.2:

"Para um melhor desempenho, o SIMD Extensions Streaming e Streaming SIMD Extensions 2 exigem que seus operandos memória a serem alinhados com limites de 16 bytes. Dados Unaligned pode causar perdas significativas de desempenho em comparação com dados alinhados."

De Apêndice D:

"É importante assegurar que o quadro de pilha está alinhada a um limite de 16 bytes na entrada função de manter os dados locais __m128, parâmetros e locais registo derramamento XMM alinhados ao longo de uma chamada de função."

http://www.intel.com/Assets/PDF/manual/ 248966.pdf

Outras dicas

Eu não tenho certeza que eu não tenho provas em primeira mão, mas acredito que a razão é SSE. SSE é muito mais rápido se seus buffers já estão alinhados em um 16 bytes de contorno (movps vs movups) e qualquer x86 tem pelo menos SSE2 para mac os x. Pode ser tomado cuidado pelo usuário do aplicativo, mas o custo é bastante significativo. Se o custo total para tornar obrigatório na ABI não é muito significativa, pode valer a pena. SSE é usado bastante incisiva no Mac OS X: acelerar o quadro, etc ...

Eu acredito que é para mantê-lo em linha com o x86-64 ABI.

Primeiro, nota que a 16 bytes alinhamento é uma excepção introduzido pela Apple para o sistema V IA-32 de ABI.

O alinhamento da pilha só é necessária quando chamando funções do sistema, porque muitas bibliotecas de sistema está a utilizar extensões SSE ou Altivec que exigem o alinhamento de 16 bytes. Eu encontrei uma referência explícita no libgmalloc página MAN .

Você pode perfeitamente lidar com o seu quadro de pilha da maneira que quiser, mas se você tentar chamar uma função do sistema com uma pilha desalinhados, você vai acabar com um misaligned_stack_error mensagem.

Editar: Para o registro, você pode se livrar de problemas de alinhamento ao compilar com GCC usando a opção mstack-novo alinhamento.

Esta é uma questão de eficiência.

Certificando-se a pilha é de 16 bytes alinhados em cada função que utiliza as novas instruções SSE adiciona muita sobrecarga para usar essas instruções, efetivamente reduzindo o desempenho.

Por outro lado, mantendo a pilha de 16 bytes alinhado em todos os momentos garante que você pode usar instruções SSE livremente com nenhuma penalidade de desempenho. Não há custo para isso (custo medida em instruções, pelo menos). Ele só envolve mudar uma constante no prólogo da função.

desperdiçando espaço de pilha é barato, é provavelmente a parte mais quente do cache.

Meu palpite é que a Apple acredita que todo mundo usa XCode (gcc) que alinha a pilha para você. Então, exigindo a pilha para ser alinhadas de modo kernel não tem que é apenas um micro-otimização.

Enquanto eu realmente não posso responder à sua pergunta de por que, você pode encontrar os manuais no seguinte site útil:

http://www.agner.org/optimize/

Em relação à ABI, ter um olhar especialmente em:

http://www.agner.org/optimize/calling_conventions.pdf

Hope isso é útil.

Hmm, não OS X ABI também fazem RISC engraçado como coisas como passar pequenas estruturas nos registos?

Assim que aponta para a consistência com a teoria outras plataformas.

Venha para pensar sobre isso, o FreeBSD syscall API também alinha valores de 64 bits. (Como por exemplo lseek e mmap)

A fim de manter a consistência no kernel. Isso permite que o mesmo kernel a ser inicializado em múltiplas arquiteturas sem modicfication.

Não sei por que ninguém tenha considerado a possibilidade de fácil portabilidade de plataforma baseada em PowerPC legado?

Leia esta:

http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/100-32-bit_PowerPC_Function_Calling_Conventions/32bitPowerPC.html#//apple_ref/doc/uid/ TP40002438-SW20

E, em seguida ampliada em "32 bits Função PowerPC Convenções de chamada" e, finalmente, o seguinte:

"Estes são os modos de alinhamento de incorporação disponíveis no 32-bit ambiente PowerPC:

modo de alinhamento de energia é derivada das regras de alinhamento utilizados pelo compilador IBM XLC para o sistema operacional AIX. É o padrão modo de alinhamento para a versão PowerPC-arquitetura do GCC usadas no AIX e Mac OS X. Como este modo é mais provável que seja compatível entre compiladores PowerPC de arquitetura de diferentes fornecedores, é tipicamente usado com estruturas de dados que são partilhados entre diferentes Programas ".

Em vista do fundo baseado em PowerPC legado da OSX, a portabilidade é uma consideração importante - que dita seguindo a convenção todo o caminho de volta para compilador XLC do AIX. Quando você pensa em termos da necessidade de certificar-se de todas as ferramentas e aplicações irão trabalhar em conjunto com um retrabalho mínimo, eu acho que é importante para manter o mesmo legado ABI, tanto quanto possível.

Isso dá a filosofia, e de continuar a leitura é a regra explicitamente mencionado ( "Prolog e Epilog"):

A função chamada é responsável por alocar um próprio quadro de pilha, tendo o cuidado de preservar o alinhamento de 16 bytes no pilha. Esta operação é realizada por uma seção de código chamado de prólogo, que os lugares compilador antes do corpo da sub-rotina. Depois que o corpo da sub-rotina, o compilador coloca um epílogo para restaurar o processador para o estado em que estava antes de a sub-rotina chamada.

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