Dê um Boost na performance do seu código em Python e R!

Dicas para avaliar e melhorar continuamente a performance de seus scripts.

A maioria das pessoas, que trabalha com análise de dados independente qual software usa, já passou por problema de performance. Caso você nunca tenha passado, considere um outlier!

Com o tempo e com muitos fracassos, montei como se fosse um manual para depois de desenvolver e testar o modelo de análise. Esse passo a passo funciona perfeitamente para momentos anteriores ao modelo pegar escalas maiores e não sofrer queda de desempenho de execução.

“Qualquer um pode escrever um código que o computador entende. Porém, apenas bons programadores escreverão códigos que humanos consigam entender.”— Martin Fowler

São basicamente 3 preocupações que você irá ter:

  • Mensurar cada bloco
  • Otimizar o código
  • Repetir as etapas anteriores

Cuidado para não cair no capricho, seja pragmático porque seu tempo é valioso demais para conseguir 0.03sec de ganho.

“Make it work, make it right, make it fast.” — Kent Beck

Mensurando a performance

A primeira etapa para otmização de performance é mensurar onde está crítico, ou seja, onde o computador gasta mais energia executando. Para isso trago exemplos de mensuração em R e Pyhton.

Em R

Tanto em R e Python existem mais de uma maneira de mensurar o seu script. No R há a biblioteca chamada lineprof . Segue um exemplo de uma função criada para demosntrar como é enxergado o output de tempo por processo.

Load e função exemplo

Aplicando lineprof devemos chamar o script, por exemplo vamos supor que salvei o bloco de código acima com o nome “profiling-example”, portanto deve-se chamar o nome do script salvo na função source() e em seguida a função que queira mensurar usando lineprof() segue uma ilustração usando o exemplo fornecido.

Mensurando o tempo de processo por função

O output mostra por etapa que pode ser observado na coluna src o tempo alocado e assim é possível ver onde custa mais tempo para o script. Todavia, quando você tem um script muito grande, fica inviável analisar esse tipo de output.

Para isso é possível analisar graficamente usando o pacote shiny a função shine() . Logo continuando com o exemplo anterior, ficaria da seguinte maneira shine(l):

Usando a função shine()

Essas colunas ao lado do código são quatros medidas de performance.

  • t —o tempo (em segundos) gasto nessa linha de código (explicado na medição de desempenho).
  • r — a memória em megabytes liberada por essa linha de código. Significa que o lançamento da memória apenas informa que a memória liberada não era mais necessária antes dessa linha.
  • a — a memória em megabytes alocada em cada linha de código.
  • d — o número de duplicações de vetores que ocorreram. Uma duplicação de vetor ocorre quando R copia um vetor como resultado de sua cópia na semântica de modificação.

Em Python

Agora em python, temos o line_profile, que é similar ao do R na maneira de usar. Entretanto as variáveis de performance são diferentes. Devemos chamar também o script que queremos medir a performance como mostra no exemplo abaixo:

Em seguida, para mostrar um output detalhado da performance do seu código:

Rodando o código acima — substituindo o script_to_profile pelo nome do arquivo python com o script que queira avaliar a performance — você gerará um output como mostra abaixo:

Tem uma forma de usar o line_profile sem precisar chamar o kernprof , abaixo segue o exemplo:

Logo, quando chamar o script para executar ele irá mostrar também um output de performance, isso se deve ao comando atexit.register(profile.print_stats) .

Essa etapa é sugerida ser primeira pelo seguinte motivo: identificar onde está sugando mais tempo de processamento. Para então atuar em cima do que irá fazer diferença no tempo total de processamento.

Otimizando o código

Look for existing solutions

A comunidade tecnológica é muito aberta em dividir soluções de muitos problemas que você possa está vivendo. Devido a isso algumas consultas nesses sites poderiam te ajudar a perder tempo em criar solução: GitHub, Stackoverflow, Quora e Medium.

Do less work

Simplista é uma característica essencial para um bom data science, evitar em criar soluções ou scripts complexos. A tecnologia vem evoluindo de uma maneira que possa tornar um trabalho muito longo em obsoleto, portanto resolva rápido.

Vectorise

Por isso que algebra linear é importante, saber montar uma matriz e entender sua lógica lhe torna apto a criar scripts com boa perfomance. Evitar for() é uma ótima iniciativa para começar a aplicar funções vetorizadas como apply() , ao invés de sum() preferir rowsum() …

Parallelise

Fazer um código em paralelo não necessariamente precisa de um super computador ou fazer via cloud. Isso se deve porque normalmente o seu computador ativa apenas um core e, tanto em R ou em Python, existem funções de ativar mais cores em seu computador. Isso irá exigir mais do seu computador, mas em muitos casos poderá ser bastante útil.

Avoid copies

Uma maneira segura para quem está começando a programar é criar versionamentos do mesmo objeto que funciona como se fosse um backup. Isso acaba alocando mais recurso sem necessidade, então meu conselho é que, na fase final de teste, passar tudo para função e esses objetos auxiliares não irão ocupar espaço, evitando problemas de performance. Além disso, seu código fica mais organizado para uma outra pessoa consultar e para debugar também.

Byte-code compile

Em resumo é escrever de uma maneira similar a linguagem nativa que normalmente é C+ ou C++. Mas acredito que quando chegar nessa etapa, cumprindo as anteriores, não será necessário porque seu código já estará performando bem.


Para buscar melhorar a performance, comece em aprender a mensurar e identificar a causa raiz. Isso irá poupar tempo e trará resultados satisfatórios. Boa sorte!

Fontes:

http://adv-r.had.co.nz/Profiling.html

https://dzone.com/articles/best-programming-jokes-amp-quotes

http://adv-r.had.co.nz/memory.html#memory-profiling