Quando é um bom momento para discutir sobre o desempenho em Haskell?

8

O próprio Simon Peyton Jones reconhece que o raciocínio sobre o desempenho em Haskell é difícil devido à semântica não estrita.

Ainda tenho que escrever um projeto significativo em haskell, então me pergunto: posso raciocinar sobre desempenho apenas no início de um projeto (ao escolher estruturas básicas de dados e biblioteca IO) e sempre que surgir um problema, lide com o criador de perfil?

Em outras palavras, é possível (por exemplo, não muito doloroso) adiar o desempenho quando você tiver problemas de desempenho ou precisa aprender a prever como o GHC executará seu código (por exemplo: inferir o que o analisador de rigidez decidirá )?

Simon Bergot
fonte
Quando o desempenho importa.
Thomas Eding

Respostas:

7

As outras respostas fornecem conselhos amplos sobre o raciocínio de desempenho. Esta resposta trata especificamente de semântica não estrita.

Embora a preguiça torne mais difícil argumentar sobre desempenho, não é tão complicado quanto você imagina. Embora a preguiça seja bastante útil em algumas situações, na maioria das vezes uma linguagem preguiçosa é usada da mesma maneira que uma linguagem estrita seria usada. Conseqüentemente, o raciocínio de desempenho para idiomas estritos pode ser aplicado (com alguns ajustes) a idiomas preguiçosos.

Em termos de complexidade de tempo, a avaliação ávida faz estritamente mais trabalho do que a avaliação preguiçosa. Ambas as estratégias produzem o mesmo resultado na maioria dos casos. (Mais precisamente, se a avaliação ágil não apresentar erros, ela produzirá o mesmo resultado que a avaliação preguiçosa.) Portanto, para raciocinar sobre a complexidade de tempo de um programa Haskell, você pode fingir que ele avalia avidamente. Nas situações pouco frequentes em que a preguiça é importante, essa estimativa será muito alta e deve ser revisada para baixo.

Embora a avaliação preguiçosa ofereça menor complexidade de tempo do que a avaliação antecipada, às vezes oferece maior complexidade de espaço, ou seja, vazamentos de espaço. Maior complexidade de espaço pode ser corrigida adicionando anotações de rigidez para fazer com que um programa seja executado com mais entusiasmo. As ferramentas de criação de perfil são muito boas para rastrear a causa dos vazamentos de espaço. Eu categorizaria isso como depuração de correção ou depuração de desempenho, dependendo da gravidade.

Dissipador de calor
fonte
In terms of time complexity, eager evaluation does strictly more work than lazy evaluation. Em que você está baseando essa afirmação? Supondo que a avaliação ansiosa termine no mesmo ponto que a avaliação preguiçosa (ou seja, não entrando na avaliação preguiçosa de sequências infinitas e coisas assim), um algoritmo de geração ansiosa será sempre tão rápido ou mais rápido (ou seja, faça menos trabalho) do que um algoritmo preguiçoso porque não exige a sobrecarga de chamadas repetidas em uma rotina de gerador.
Mason Wheeler
2
Eu acho que a razão de eu amo vocês, Haskell, é porque eu mal entendo o que você está falando.
Erik Reppen
3
@MasonWheeler: Ele provavelmente está falando sobre complexidade assintótica . Os fatores constantes são um problema de implementação. Além disso, mesmo que ambos os programas terminem, o não-estrito poderia fazer um trabalho significativamente menor: considere all even [1..1e10]uma versão estrita e uma preguiçosa all. O compilador também tem mais margem de manobra para escolher a ordem da avaliação em uma linguagem como Haskell com coisas como fusão de loop.
Tikhon Jelvis
1
A avaliação Lazy @MasonWheeler evita avaliar quaisquer termos que não são necessários. Não consegui encontrar uma referência autorizada, mas aqui está uma que indica que a avaliação lenta realiza menos reduções do que a avaliação inicial: en.wikibooks.org/wiki/Haskell/…
Dissipador de calor
1

Otimize as grandes coisas antes de codificar e as pequenas coisas quando terminar.

Por exemplo, antes de começar a codificar, você deve pensar no seguinte:

  • As bibliotecas / estruturas que você vai usar decentemente são rápidas?
  • Tente manter suas estruturas de dados simples.
  • Tente manter seus algoritmos e padrões de design o mais simples possível.
  • Qual a velocidade do idioma que estou usando?

...e assim por diante.

Então, quando você estiver quase terminando o seu código, pense nas pequenas coisas como qual função interna é mais rápida, devo reescrever essa área de código para torná-la mais eficiente etc.

Isso vale para qualquer idioma e realmente depende do tipo de software que você está escrevendo. Haskell é uma linguagem de uso geral, então você provavelmente (me corrija se eu estiver errado) não fazendo nada que precise ser extremamente rápido. Nesse caso, você deve usar um idioma de nível inferior. Se a velocidade é um problema, mas não o suficiente para usar um idioma de baixo nível, você deve otimizar seu desempenho com base no exposto acima.

Obviamente, todo mundo faz as coisas de maneira diferente; portanto, se sua experiência pessoal faz você pensar que deveria fazê-lo de maneira diferente com base na sua situação, provavelmente deveria.

Dinâmico
fonte
5
O problema é que, na maioria dos idiomas, posso argumentar facilmente sobre o comportamento em tempo de execução. Em haskell, isso é muito mais difícil. Portanto, é mais provável que você adote uma abordagem errada e aumente a probabilidade de erros de desempenho.
Simon Bergot
A resposta começa bem, então você diz "veja as pequenas coisas que podem ser melhoradas" ... sim, não. Perfil.
Florian Margaine
3
Essa resposta é muito ampla e não é muito útil para Haskell. Suponha que o OP já conheça macro e micro otimização. Como essa resposta se aplica ao Haskell , uma linguagem não rígida para a qual é mais difícil argumentar sobre o tempo de execução e o desempenho da memória?
Andres F.
@FlorianMargaine Profile?
Dynamic
0

Eu gostaria de adicionar à resposta do Dynamic:

  • Faça seu código modular e fracamente acoplado .
  • Ocultar detalhes de implementação dos seus módulos.

Quando você perceber mais tarde no desenvolvimento quais gargalos seu código possui, pode ser realmente doloroso refatorar todo o projeto. Se o seu código estiver bem estruturado, os gargalos serão mais fáceis de encontrar e otimizar / corrigir.

Petr Pudlák
fonte