39 pontos por lemonmint 2024-12-11 | Ainda não há comentários. | Compartilhar no WhatsApp

Equívocos sobre otimização de compiladores

  • A otimização fornece o programa ótimo?
    • O objetivo do compilador não é gerar o programa ótimo, mas melhorar um programa simplificado.
    • A otimização de tamanho de código pode ser viável, mas a otimização de tempo de execução é difícil devido à dificuldade de medição, à ausência de subestrutura ótima e à imprecisão dos modelos de hardware.
    • Ao contrário do tamanho do código, o tempo de execução é difícil de medir com precisão, é afetado por vários fatores e não possui subestrutura ótima. Por exemplo, mesmo que dois loops sejam otimizados individualmente, para otimizar o programa inteiro talvez seja necessário fundi-los. Além disso, a otimização é difícil porque não existe um modelo exato do hardware de destino. Por exemplo, o goSLP gera código de vetorização SLP globalmente otimizado, mas, como o modelo de hardware é impreciso, o programa gerado pode não ser ótimo e até ser mais lento que o LLVM.

Equívocos sobre predição de desvio

  • Os pesos de desvio são usados pelo preditor de desvios da CPU?
    • Na arquitetura x86, o compilador não gera dicas de desvio.
    • Os pesos de desvio são usados pelo compilador para o posicionamento de blocos de código. (Ex.: se a probabilidade de desvio for alta, o bloco de destino é colocado logo abaixo do bloco atual para aumentar a localidade no cache de instruções.)
    • Na arquitetura Intel Redwood Cove mais recente, as dicas de desvio voltaram a ter alguma relevância, mas ainda é raro que compiladores realmente gerem essas dicas.

Equívocos sobre níveis de otimização

  • -O3 gera código muito mais rápido que -O2?
    • No caso do Clang, a diferença de desempenho entre -O2 e -O3 não é grande; no caso do GCC, há uma pequena diferença porque o -O2 é menos agressivo que o do Clang.
    • O -O3 quase não considera o tamanho do código, então podem surgir problemas de cache de instruções.
    • É melhor verificar com benchmarking.

Equívocos sobre interpretadores Javascript e compiladores JIT

  • Interpretadores Javascript fazem compilação JIT em tempo de execução porque não é possível saber antecipadamente quais caminhos são quentes?
    • Saber quais são os caminhos quentes, por si só, não é suficiente; informações de tipo também são necessárias.
    • Como as informações de tipo só podem ser conhecidas em tempo de execução, compiladores JIT compilam o código nesse momento.

Equívocos sobre a relação entre compiladores e interpretadores

  • Se existe um compilador, um interpretador não é necessário?
    • No caso de C/C++, interpretadores não são muito úteis, mas em casos como WebAssembly eles podem oferecer vantagens como facilidade de desenvolvimento e uso, depuração e segurança.

Equívocos sobre o estágio intermediário do compilador

  • O middle-end é independente do alvo/plataforma?
    • No caso do LLVM, o estágio intermediário não é totalmente independente do alvo/plataforma.

Equívocos sobre otimização de localidade de dados

  • O compilador otimiza a localidade de dados?
    • Compiladores otimizam a localidade no cache de instruções, mas quase não otimizam a localidade de dados.
    • Otimizar localidade de dados exige grandes mudanças no código, e compiladores de C/C++ não conseguem fazer essas mudanças.
    • Para melhorar a localidade de dados, é preciso usar técnicas como design orientado a dados.

Equívocos sobre velocidade de compilação

  • -O0 oferece compilação rápida?
    • O -O0 gera código depurável e previsível, mas nem sempre garante compilação rápida.
    • Em geral, -O0 é mais rápido que -O2, mas isso pode variar conforme o tamanho do projeto e o compilador.
    • Para compilação rápida, é possível considerar contornar o pipeline padrão de compilação (ex.: TinyCC) ou gerar LLVM IR diretamente.

Equívocos sobre velocidade de compilação de templates

  • Templates são lentos para compilar?
    • O motivo de templates em C++ compilarem lentamente está no modelo de compilação do C++.
    • Templates em si não degradam drasticamente a velocidade de compilação.
    • A biblioteca padrão Phobos de Dlang usa muitos templates, mas compila rapidamente.

Equívocos sobre o valor da compilação separada

  • A compilação separada sempre vale a pena?
    • A compilação separada pode levar a tempos de link longos.
    • Em muitos projetos, builds unity (incluir todo o código em um único arquivo) oferecem melhor desempenho.
    • Builds unity trazem vantagens como otimização do programa inteiro, maior velocidade de compilação e melhores logs de erro.
    • É raro que a compilação separada seja melhor do que um build unity.

Equívocos sobre otimização em tempo de link (LTO)

  • Por que a otimização em tempo de link (LTO) acontece no momento do link?
    • A LTO é realizada para otimização do programa inteiro.
    • Em teoria, seria mais sensato fazer a otimização do programa inteiro no estágio intermediário, mas, por problemas práticos dos sistemas de build de C/C++ (dificuldade de encontrar arquivos-fonte e identificar relações de chamada), ela é feita no tempo de link.
    • Como o linker consegue encontrar todos os object files, o compilador inclui representações intermediárias como LLVM IR nesses arquivos para que o linker possa acessá-las.

Equívocos sobre otimização por inlining

  • Inlining é útil principalmente porque remove instruções de chamada de função?
    • Remover instruções de chamada de função é uma vantagem, mas o maior benefício do inlining é permitir outras otimizações.
    • O inlining possibilita otimizações entre funções.
    • Quando o código de várias funções é combinado em uma só por meio do inlining, técnicas de otimização antes aplicadas apenas dentro de uma função podem então ser usadas.

Equívocos sobre o papel da palavra-chave inline

  • A palavra-chave inline tem relação com a otimização por inlining?
    • Em C++, a palavra-chave inline originalmente era usada como dica para o otimizador, mas desde o C++98 passou a significar "múltiplas definições permitidas".
    • No caso do LLVM, a presença da palavra-chave inline adiciona o atributo inlinehint e aumenta o limiar de inlining, mas o efeito não é grande.
    • Para sempre fazer inline de uma função, é preciso usar o especificador always_inline.

Equívocos sobre materiais de estudo para compiladores

  • LLVM é o melhor compilador para aprender?
    • O LLVM também tem valor educacional, mas, por suportar muitos casos de uso diferentes, é complexo e enorme.
    • Para aprender desenvolvimento de compiladores, é melhor observar primeiro compiladores menores e mais simples, como o compilador Go, LDC e DMD.

Equívocos sobre comportamento indefinido (Undefined Behavior)

  • Comportamento indefinido só possibilita otimizações?

    • Comportamento indefinido também pode desativar otimizações.
  • O compilador pode simplesmente definir o comportamento indefinido?

    • O compilador pode definir comportamento indefinido, mas isso pode afetar o desempenho.
    • Seria ideal que o compilador definisse todo comportamento indefinido de acordo com o comportamento da plataforma, mas isso não é algo fácil de fazer na prática.

Equívocos sobre geração de código baseada em IA

  • Geração de código com 99% de precisão é aceitável?
    • Em compiladores, código gerado com 99% de precisão é difícil de usar na prática.
    • Um erro em 1% do código causa grandes dificuldades para depuração e manutenção.
    • Em projetos de grande escala, esse 1% de erro pode causar problemas muito sérios.
    • Como os LLMs atuais são muito lentos em comparação com compiladores, eles não são adequados para geração de código online.

Ainda não há comentários.

Ainda não há comentários.