
Colocamos as mãos em Cythona, graças ao auto-isolamento. O problema é prosaico - como acelerar em python com perda mínima de sintaxe. Uma abordagem é usar Cython (uma mistura de C e python).
A publicação com um título alto não deu descanso . Porém, pouco se pode aprender com o conteúdo da publicação, uma vez que as fórmulas e a tabela resultante estão incorretas. Vamos tentar completar a imagem iniciada pelos autores do post e pontuar o e.
* Os testes foram realizados no odroid xu4, ubuntu mate, python 2.7.17.
Cython é fácil de instalar (pip install cython).
Vamos torturar todos os mesmos números de Fibonacci. Vamos criar arquivos para testes de ganho de desempenho. Para linguagem python (test.py):
def test(n):
a, b = 0.0, 1.0
for i in range(n):
a, b = a + b, a
print (a)
Para linguagem cython (test2.pyx):
def test2(int n):
cdef int i
cdef double a=0.0, b=1.0
for i in range(n):
a, b = a + b, a
print (a)
O arquivo cython requer pré-construção. Vamos criar um setup.py para ele com o seguinte conteúdo:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('test2.pyx'))
E colete:
python setup.py build_ext --inplace
Agora, vamos pegar o arquivo da postagem mencionada com testes e corrigi-lo um pouco, adicionando a capacidade de inserir seu próprio número no início (tests.py):
import test
import test2
import time
number = input('enter number: ')
start = time.time()
test.test(number)
end = time.time()
py_time = end - start
print("Python time = {}".format(py_time))
start = time.time()
test2.test(number)
end = time.time()
cy_time = end - start
print("Cython time = {}".format(cy_time))
print("Speedup = {}".format(py_time / cy_time))
Vamos ver o que aconteceu:
python tests.py
Resultados:
para python 2.7:
enter number: 10
Python time = 1.62124633789e-05
Cython time = 4.05311584473e-06
Speedup = 4.0
enter number: 100
Python time = 3.40938568115e-05
Cython time = 5.00679016113e-06
Speedup = 6.80952380952
enter number: 1000
Python time = 0.000224113464355
Cython time = 1.19209289551e-05
Speedup = 18.8
enter number: 100000
Python time = 0.0200171470642
Cython time = 0.000855922698975
Speedup = 23.3866295265
Para python 3:
enter number: 10
Python time = 7.653236389160156e-05
Cython time = 2.8133392333984375e-05
Speedup = 2.7203389830508473
enter number: 100
Python time = 8.678436279296875e-05
Cython time = 3.170967102050781e-05
Speedup = 2.736842105263158
enter number: 1000
Python time = 0.00031876564025878906
Cython time = 4.673004150390625e-05
Speedup = 6.821428571428571
enter number: 100000
Python time = 0.01643967628479004
Cython time = 0.0004260540008544922
Speedup = 38.5858981533296
* o módulo test2.pyx foi “reconstruído” com o comando:
python3 setup.py build_ext --inplace
** instalado por cython:
pip3 install cython
Você pode fazer sem construir test2.pyx usando setup.py, para isso você só precisa adicionar as linhas ao arquivo tests.py :
import pyximport
pyximport.install()
Agora test2.pyx será compilado rapidamente cada vez que tests.py for executado e haverá menos arquivos na pasta.
Como iniciar o cython no Windows.
Apesar do cython permitir a montagem de arquivos para python3 e python2,
Com python3, o comando build funciona:
python setup.py build_ext -i --compiler=msvc
No entanto, para seu trabalho completo, é necessário instalar parte dos componentes do visual studio 2019. O que exatamente instalar está indicado na solução aqui .
Portanto, existem duas opções de trabalho que permitem trabalhar (construir um arquivo) no Windows com cython.
O primeiro usa python2.7 e o compilador mingw.
O procedimento é o seguinte.
1. Instale o próprio cython em python 2.7:
py -2 -m pip install cython
2. Instale o compilador mingw:
mingw
3. Depois de instalar o compilador e adicioná-lo às janelas PATH, o arquivo .pyx pode ser compilado com o comando:
python setup.py build_ext -i --compiler=mingw32
O segundo está usando python3.x e o compilador msvc.
Como executar cython no notebook Jupyter.
Às vezes é necessário testar o trabalho do código visualmente usando o jupyter. Para não compilar o código em cmd todas as vezes, você pode usar cython diretamente nas células jupyter.
Para fazer isso, importe cython executando na célula jupyter:
%load_ext cython
E vamos executar algum código na próxima célula:
%%cython -a
import numpy as np
cdef int max(int a, int b):
return a if a > b else b
cdef int chebyshev(int x1, int y1, int x2, int y2):
return max(abs(x1 - x2), abs(y1 - y2))
def c_benchmark():
a = np.random.rand(1000, 2)
b = np.random.rand(1000, 2)
for x1, y1 in a:
for x2, y2 in b:
chebyshev(x1, x2, y1, y2)
Se tudo der certo, a saída será assim:
