Quanto o software científico deve ser otimizado?

13

Para aplicativos que exigem recursos computacionais significativos, o alto desempenho pode ser um fator crítico quando se trata de fornecer resultados científicos ou obter "avanços" em tempo razoável.

Quanto tempo e esforço os desenvolvedores de software devem investir na otimização de um aplicativo? Quais são os principais critérios utilizados?

Allan P. Engsig-Karup
fonte
Os programas que os cientistas escrevem geralmente são executados por um período muito longo (por exemplo, simulações). O tempo do programador e o tempo de execução do computador podem ser comparáveis. Isso é muito diferente do trabalho programador "usual" de hoje. Como nos primeiros dias da computação, geralmente vale a pena investir algum esforço (e tempo do programador) para acelerar a simulação e terminar mais rapidamente, além de realizar o trabalho mais rapidamente.
Szabolcs

Respostas:

15

Na grande maioria dos casos, melhorias nos algoritmos fazem uma diferença maior do que melhorias na otimização. Os algoritmos também são mais portáteis que as otimizações de baixo nível. Meu conselho é seguir as práticas recomendadas gerais em relação ao layout da memória para reutilização do cache, evitando cópias ou comunicação excessivas, tratando o sistema de arquivos de maneira sadia e fazendo com que os kernels de ponto flutuante tenham granularidade suficiente para vetorização. Às vezes, isso é suficiente para atingir uma fração aceitavelmente alta de "pico" (para esta operação).

Sempre esboce um modelo de desempenho para operações que você considera importantes (ou que você descobre serem importantes por criação de perfil). Em seguida, você pode usar o modelo de desempenho para estimar o que uma implementação altamente ajustada poderia oferecer. Se você decidir que a aceleração vale a pena (em relação às outras coisas que você poderia estar fazendo), faça a otimização.

Talvez o desafio mais difícil seja projetar interfaces e estruturas de dados importantes e de alto nível (no sentido de que muito código dependerá dessas opções) para que você possa otimizar mais tarde sem precisar alterar a API. Ao contrário de otimizações específicas e diretrizes gerais, não sei como ensinar isso, exceto através da experiência. Trabalhar com software de código aberto sensível ao desempenho ajuda. Como em qualquer decisão da API, é importante entender o espaço do problema.

Jed Brown
fonte
1
Recentemente, obtive um fator de melhoria de 10.000 (para nossos maiores eventos) no tempo de execução de uma etapa limitante de nossa análise, apenas substituindo um algoritmo que era O (n ^ 2) no tempo e no espaço por um O (n log n ) em ambos. Mente-lhe que significava outra dependência e alguns complexidade adicional, mas às vezes vale a pena ...
dmckee --- ex-moderador gatinho
1
Os fatores de aceleração (que são relativos a alguma coisa) não valem muito a pena uma referência clara ao que você comparou. Se você comparar com uma implementação ruim com base em um algoritmo inapropriado e depois alterar, obviamente não seria razoável esperar grandes ganhos relativos.
Allan P. Engsig-Karup
1
@ Allan: Havia um fator de 10.000 para obter uma única alteração e, obviamente , foi uma implementação mal escolhida. O código anterior foi prejudicado tanto pelo espaço desnecessário quanto pela complexidade do tempo: o desempenho do armazenamento em cache era péssimo. Mas esse é o ponto, não é?
dmckee --- ex-moderador gatinho
8

Como você definiria "otimizar"? Existe todo um espectro, desde o desenvolvimento de melhores algoritmos ou modelos computacionais até o uso de montador ajustado manualmente.

Na minha opinião e experiência, a fruta mais baixa está em algum lugar no meio, por exemplo, escolhendo um algoritmo que seja mais adequado à arquitetura subjacente do computador. O algoritmo não precisa necessariamente ser novo e seu entendimento da arquitetura subjacente não precisa necessariamente ser muito específico, por exemplo,

  • Se você sabe que sua arquitetura suporta SIMD, reestruture o cálculo para que suas operações possam ser escritas em termos de vetores curtos,
  • Se você sabe que a arquitetura é um computador com vários núcleos, tente dividir sua tarefa computacional em subtarefas individuais que não interferem entre si e executá-las em paralelo (pense no DAG de suas subtarefas) ,
  • Se sua arquitetura subjacente tiver uma GPU, pense em maneiras de reformular sua computação como um grupo de threads que marcham pelos dados na etapa de bloqueio,
  • etc ...

Todos os recursos acima, por exemplo, SIMD, paralelismo e GPUs, podem ser acessados ​​sem muito conhecimento de baixo nível, mas apenas oferecem realmente uma vantagem em algoritmos que podem explorá-los facilmente.

Pedro
fonte
4

Concordo com todas as respostas já apresentadas até agora ... Quero apenas abordar mais um aspecto esquecido da otimização de código: expectativa de qualidade.

O problema da otimização de código geralmente surge quando o usuário tenta resolver problemas cada vez maiores e o código é insuficiente para atender às necessidades / expectativas do usuário. A quantidade de tempo que se deve investir na otimização de código depende da demanda para atender a essa expectativa. Certamente vale a pena investir um tempo significativo se houver uma necessidade crítica de uma vantagem competitiva (por exemplo, finalizando e publicando sua pesquisa sobre um tópico importante antes de outros).

Obviamente, quanto tempo deve ser investido depende de quão rápido você precisa e de quão portátil você deseja que o código seja. Freqüentemente, essas duas necessidades estão em conflito umas com as outras e você precisa decidir qual é mais importante antes de começar a otimização. Quanto mais portátil você desejar, mais precisará confiar em alterações de design de alto nível no código (estrutura de algoritmo / dados). Quanto mais rápido você deseja que o código seja executado, ele deve ser ajustado com otimizações de baixo nível específicas para uma máquina específica (por exemplo, otimizações de código / compilador / tempo de execução).

Paulo
fonte
4

Você terá que fazer a análise (de custo) de gastar tantos meses-homem (e esses são sempre míticos :-)) para ganhar velocidade de execução. Você terá que descobrir quantas vezes esse software será usado e quantas pessoas poderão estimar o ganho.

A regra de ouro, como sempre, é a famosa regra 80/20. Em algum momento, não é mais necessário gastar cada vez mais tempo para ganhar poucas porcentagens (ou menos) de tempo de execução. Mas você terá que analisar.

E concordo sinceramente com os pôsteres acima: verifique se a sua API está bem pensada, para que não precise de muitas alterações e se o código é portátil e sustentável (pense em ter que re-analisar um algoritmo que você escreveu e com detalhes) otimizado há dez anos). E certifique-se de usar boas práticas de programação e bibliotecas padrão. É provável que alguém já tenha pensado no algoritmo mais eficiente para sua aplicação.

Para citar Donald Knuth: "a otimização prematura é a raiz de todo mal". Portanto, analise seu código, mas não muito cedo.

GertVdE
fonte
Você está se referindo à regra do princípio de Pareto (80/20)? Em caso afirmativo, você quer dizer que devemos concentrar os esforços de otimização nos 20% do código que produz 80% da desaceleração? Ou você quer dizer que, se você pode esperar apenas 20% de aceleração, simplesmente não vale a pena otimizar?
Paul
Não, eu apenas o usei como um tipo de princípio, não exatamente 80/20. Em algum momento, você gastará tanto esforço para ganhar apenas algumas porcentagens que não valerá mais o esforço.
GertVdE
3

Alguns conselhos adicionais:

  1. Antes de fazer qualquer otimização de um programa de trabalho, verifique se você possui um bom conjunto de casos de teste que ajudam a manter a integridade do código. Não faz sentido obter resultados errados mais rapidamente.
  2. Se sua otimização tornar o código menos legível, mantenha a versão original por perto, pelo menos na forma de um comentário, mas melhor como uma versão alternativa a ser selecionada no tempo de compilação e no tempo de execução. Suas necessidades de otimização podem mudar à medida que seus problemas e suas máquinas evoluem, e o código original pode ser um melhor ponto de partida para a otimização que você fará daqui a cinco anos.
  3. Se sua versão otimizada tiver um impacto mínimo, mas tornar o código menos legível, menos universal ou menos estável, volte para a versão original. Você perde mais do que ganha.
Khinsen
fonte