Pergunta

Embora fosse muito conveniente usar funções inline em algumas situações,

Há alguma desvantagem nas funções inline?

Conclusão:

Aparentemente, não há nada de errado em usar funções embutidas.

Mas vale a pena observar os seguintes pontos!

  • O uso excessivo de inlining pode tornar os programas mais lentos.Dependendo do tamanho de uma função, inlinhá-la pode fazer com que o tamanho do código aumente ou diminua.Incorporar uma função de acesso muito pequena geralmente diminuirá o tamanho do código, enquanto incorporar uma função muito grande pode aumentar drasticamente o tamanho do código.Em processadores modernos, códigos menores geralmente são executados mais rapidamente devido ao melhor uso do cache de instruções. - Diretrizes do Google

  • Os benefícios de velocidade das funções inline tendem a diminuir à medida que a função aumenta de tamanho.Em algum momento, a sobrecarga da chamada de função torna-se pequena em comparação com a execução do corpo da função e o benefício é perdido - Fonte

  • Existem algumas situações em que uma função inline pode não funcionar:

    • Para uma função que retorna valores;se existir uma instrução de retorno.
    • Para uma função que não retorna nenhum valor;se existir uma instrução loop, switch ou goto.
    • Se uma função for recursiva. -Fonte
  • O __inline palavra-chave faz com que uma função seja incorporada somente se você especificar a opção de otimização.Se otimizar for especificado, seja ou não __inline é respeitado depende da configuração da opção do otimizador embutido.Por padrão, a opção inline entra em vigor sempre que o otimizador é executado.Se você especificar Optimize , deverá também especificar a opção noinline se quiser que o __inline palavra-chave a ser ignorada. -Fonte

Foi útil?

Solução

Vale ressaltar que a palavra-chave inline é, na verdade, apenas uma dica para o compilador.O compilador pode ignorar o inline e simplesmente gerar código para a função em algum lugar.

A principal desvantagem das funções inline é que elas podem aumente o tamanho do seu executável (dependendo do número de instanciações).Isso pode ser um problema em algumas plataformas (por exemplo.sistemas embarcados), especialmente se a função em si for recursiva.

Eu também recomendo criar funções embutidas muito pequeno - Os benefícios de velocidade das funções inline tendem a diminuir à medida que a função aumenta de tamanho.Em algum momento, a sobrecarga da chamada de função torna-se pequena em comparação com a execução do corpo da função e o benefício é perdido.

Outras dicas

Isso poderia aumentar o tamanho do executável, e eu não acho que os compiladores sempre os tornarão embutidos, mesmo que você tenha usado a palavra -chave embutida.(Ou é o contrário, como o que Vaibhavdisse?...)

Eu acho que geralmente tudo bem se a função tiver apenas 1 ou 2 instruções.

Editar: Aqui está o que o Linux Estilo de codificação documento diz sobre isso:

Capítulo 15:A doença inline

Parece haver uma percepção errônea comum de que o GCC tem uma opção de aceleração mágica "Faça -me mais rápido" chamado "Inline".Embora o uso de inlações possa ser apropriado (por exemplo, como um meio de substituir macros, consulte o Capítulo 12), muitas vezes não é.O uso abundante da palavra -chave embutida leva a um kernel muito maior, que por sua vez diminui o sistema como um todo, devido a uma pegada maior da ICACH para a CPU e simplesmente porque há menos memória disponível para o Pagecache.Basta pensar nisso;Uma Miss Pagecache causa uma busca de disco, que leva facilmente 5 milissegundos.Existem muitos ciclos de CPU que podem entrar nesses 5 milissegundos.

Uma regra razoável é não colocar em linha em funções com mais de 3 linhas de código nelas.Uma exceção a esta regra são os casos em que um parâmetro é conhecido por ser uma constante de compilação e, como resultado dessa constante saber O compilador poderá otimizar a maior parte da sua função no momento da compilação.Para um bom exemplo deste caso posterior, consulte a função embutida kmalloc ().

Freqüentemente, as pessoas argumentam que adicionar embutido às funções estáticas e usadas apenas uma vez é sempre uma vitória, pois não há troca espacial.Embora isso esteja tecnicamente correto, o GCC é capaz de continá -los automaticamente sem ajuda, e o problema de manutenção de remover o inline quando um segundo usuário aparece supera o valor potencial da dica que diz ao GCC para fazer algo que teria feito de qualquer maneira.

Concordo com os outros posts:

  • inline pode ser supérfluo porque o compilador fará isso
  • inline pode inchar seu código

Um terceiro ponto é que isso pode forçá-lo a expor detalhes de implementação em seus cabeçalhos, por exemplo,

class OtherObject;

class Object {
public:
    void someFunc(OtherObject& otherObj) {
        otherObj.doIt(); // Yikes requires OtherObj declaration!
    }
};

Sem o inline, uma declaração direta de OtherObject era tudo que você precisava.Com o embutido, seu cabeçalho precisa da definição para o outro objeto.

Como outros mencionaram, a palavra-chave inline é apenas uma dica para o compilador.Na verdade, a maioria dos compiladores modernos irá ignorar completamente esta dica.O compilador tem sua própria heurística para decidir se deve incorporar uma função e, francamente, não quer seu conselho, muito obrigado.

Se você realmente deseja fazer algo embutido, se você realmente criou o perfil e analisou a desmontagem para garantir que a substituição da heurística do compilador realmente faz sentido, então é possível:

  • No VC++, use a palavra-chave __forceinline
  • No GCC, use __attribute__((always_inline))

A palavra-chave inline tem um segundo propósito válido - declarar funções em arquivos de cabeçalho, mas não dentro de uma definição de classe.A palavra-chave inline é necessária para informar ao compilador para não gerar múltiplas definições da função.

Há um problema com o inline - uma vez que você definiu uma função em um arquivo de cabeçalho (o que implica inline, seja explícito ou implícito, definindo o corpo de uma função membro dentro da classe), não há uma maneira simples de alterá-la sem forçar seus usuários a recompilar (em oposição a revincular).Muitas vezes isso causa problemas, especialmente se a função em questão estiver definida em uma biblioteca e o cabeçalho fizer parte de sua interface.

Eu duvido.Até o compilador incorpora automaticamente algumas funções para otimização.

Não sei se minha resposta está relacionada à pergunta, mas:

Ser muito cuidado com os métodos virtuais embutidos!Alguns compiladores com bugs (versões anteriores do Visual C++, por exemplo) gerariam código embutido para métodos virtuais onde o comportamento padrão era não fazer nada além de descer na árvore de herança e chamar o método apropriado.

Incorporar funções maiores pode tornar o programa maior, resultando em mais perdas de cache e tornando-o mais lento.

Decidir quando uma função é pequena o suficiente para que o inlining aumente o desempenho é bastante complicado. Guia de estilo C++ do Google recomenda apenas funções inlining de 10 linhas ou menos.

Você também deve observar que a palavra-chave inline é apenas uma solicitação.O compilador pode optar por não incorporá-lo, da mesma forma, o compilador pode optar por criar uma função inline que você não definiu como inline se achar que a compensação velocidade/tamanho vale a pena.

Essa decisão geralmente é tomada com base em uma série de coisas, como a configuração entre otimizar para velocidade (evita a chamada de função) e otimizar para tamanho (o inlining pode causar inchaço no código, portanto não é ótimo para funções grandes usadas repetidamente).

com o compilador VC++ você pode substituir essa decisão usando __forceinline

ASSIM em geral:Use inline se você realmente deseja ter uma função em um cabeçalho, mas em outros lugares não faz muito sentido, porque se você ganhar alguma coisa com isso, um bom compilador a tornará inline para você de qualquer maneira.

O inlining excessivo de funções pode aumentar o tamanho do executável compilado, o que pode ter um impacto negativo no desempenho do cache, mas hoje em dia o compilador decide sobre o inlining de funções por conta própria (dependendo de muitos critérios) e ignora a palavra-chave inline.

Entre outros problemas com funções inline, que tenho visto muito usadas (vi funções inline de 500 linhas), o que você deve estar ciente é:

  • construir instabilidade

    • Alterar a origem de uma função embutida faz com que todos os usuários do cabeçalho recompilem
    • #includevazou para o cliente.Isso pode ser muito desagradável se você retrabalhar uma função embutida e remover um cabeçalho que não é mais usado e no qual algum cliente confiou.
  • tamanho executável

    • Cada vez que um inline é embutido em vez de uma instrução de chamada, o compilador precisa gerar todo o código do inline.Isto é bom se o código da função for curto (uma ou duas linhas), não tão bom se a função for longa
    • Algumas funções podem produzir muito mais código do que parece à primeira vista.O caso em questão é um destruidor 'trivial' de uma classe que possui muitas variáveis ​​de membro não pertencentes ao pod (ou duas ou três variáveis ​​de membro com destruidores bastante confusos).Uma chamada deve ser gerada para cada destruidor.
  • tempo de execução

    • isso depende muito do cache da CPU e das bibliotecas compartilhadas, mas a localidade de referência é importante.Se o código que você está incorporando estiver mantido no cache da CPU em um só lugar, vários clientes poderão encontrar o código e não sofrer uma falta de cache e a subsequente busca de memória (e pior, caso aconteça, uma busca de disco) .Infelizmente, este é um daqueles casos em que você realmente precisa fazer uma análise de desempenho.

O padrão de codificação em que trabalho limita as funções inline a setters/getters simples e diz especificamente que os destruidores não devem estar inline, a menos que você tenha medições de desempenho para mostrar que o inlining confere uma vantagem notável.

  1. Como outras pessoas disseram, a função inline pode criar um problema se o código for grande. Como cada instrução é armazenada em um local de memória específico, a sobrecarga da função inline faz com que o código demore mais para ser executado.

  2. existem algumas outras situações em que o inline pode não funcionar

    1. não funciona no caso de função recursiva.
    2. Também pode não funcionar com variável estática.
    3. também não funciona caso haja uso de loop, switch etc. ou podemos dizer isso com múltiplas instruções.
    4. E a função main não pode funcionar como função inline.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top