Otimizando o Python: Cython

Otimizar um programa é fazer com que este programa ou algumas de suas funções rode mais rápido.Uma regra básica é que quanto menor o nível da linguagem de programação (quanto mais perto da linguagem de máquina) maior a possibilidade de otimização.

python

A linguagem Python é famosa por ser uma linguagem de alto nível e de alta produtividade por facilitar a vida do programador. A linguagem C é famosa por ser uma linguagem de baixo nível extremamente eficiente em termos computacionais.

Uma forma comum de otimizar o código Python fazer com que ele execute módulos escritos em C, a biblioteca padrão do Python vem com uma porção de módulos que funcionam assim, por exemplo o itertools. Algumas bibliotecas externas também usam este recurso para maior eficiência, o Numpy é um ótimo exemplo, ele é extremamente eficiente.

Para o usuário é possível escrever suas próprias extensões em C que podem ser chamadas diretamente pelo código Python, contudo isto requer o conhecimento avançado de C.

A biblioteca Cython elimina esta dificuldade, com ela é possivel escrever extensões em Python que são convertidas para uma forma mais eficiente em C, são compiladas e podem ser chamadas como módulos com o comando import.

Abaixo segue um exemplo onde a concatenação de duas strings é repetida 70 milhões de vezes, esta operação é realizada primeiro em Python e depois em um  módulo convertido para C, sobre como usar o Cython, consultar a documentação.

import cProfile
import pyximport
pyximport.install()
import Cythonteste

def juntar_texto(texto1, texto2):
    for i in range(70000000):
        texto_final = texto1+texto2

print "Normal: ----------------------------------------------------"
cProfile.run("juntar_texto('Feliz ', '2013')")
print "Cython: ----------------------------------------------------"
cProfile.run("Cythonteste.juntar_texto('Feliz ', '2013')")

O módulo Cythonteste consiste de um arquivo com exatamente a mesma função juntar_texto, ele é convertido e compilado automaticamente pelo módulo pyximport.
Para medir o tempo de execução é utilizado o cProfile. Veja o resultado, são gastos 8.51 segundos no Python contra 2.35 segundo no código compilado para rodar a mesma função.

Normal: ----------------------------------------------------
4 function calls in 8.509 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
 1 0.000 0.000 8.509 8.509 <string>:1(<module>)
 1 6.053 6.053 8.509 8.509 teste_comparativo.py:6(juntar_texto)
 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
 1 2.456 2.456 2.456 2.456 {range}

Cython: ----------------------------------------------------
 3 function calls in 2.352 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
 1 0.000 0.000 2.352 2.352 <string>:1(<module>)
 1 2.352 2.352 2.352 2.352 {Cythonteste.juntar_texto}
 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}

O Cython possui ainda outros recursos que este simples exemplo não aborda, vale a pena dar uma no site.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s