我试图学习并使用cython加速我的个人项目,但我发现了一些奇怪的东西。
示例:
试用http://nealhughes.net/cython1/
中的rbf_network示例import numpy as np
# generate dummy data
n = 1000
a = np.random.uniform(low=0, high=10, size=n)
b = np.random.choice(2, 1000)
# map the function
start = time.time()
out = [a[i] if b[i] == 0 else -1/a[i] for i in range(n)]
print time.time() - start
File1和File2都包含:
import pyximport; pyximport.install()
from src.test_cython import rbf_network # File1: /src/test_cython.pyx
# from src.test import rbf_network # File2: /src/test.py
import time
import cProfile
import numpy as np
def fun():
D = 5
N = 1000
X = np.array([np.random.rand(N) for d in range(D)]).T
beta = np.random.rand(N)
theta = 10
rbf_network(X, beta, theta)
# With CProfile
cProfile.run('fun()', sort='cumtime')
# Without Cprofile
start = time.time()
fun()
print("Time without CProfile: ", time.time() - start)
File1上的输出(cythonized):
from math import exp
import numpy as np
def rbf_network(X, beta, theta):
N = X.shape[0]
D = X.shape[1]
Y = np.zeros(N)
for i in range(N):
for j in range(N):
r = 0
for d in range(D):
r += (X[j, d] - X[i, d]) ** 2
r = r**0.5
Y[i] += beta[j] * exp(-(r * theta)**2)
return Y
File2上的输出(非cython):
13 function calls in 3.920 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 3.920 3.920 {built-in method builtins.exec}
1 0.000 0.000 3.920 3.920 <string>:1(<module>)
1 0.000 0.000 3.920 3.920 run.py:138(fun)
1 3.920 3.920 3.920 3.920 {src.test_cython.rbf_network}
1 0.000 0.000 0.000 0.000 run.py:141(<listcomp>)
6 0.000 0.000 0.000 0.000 {method 'rand' of 'mtrand.RandomState' objects}
1 0.000 0.000 0.000 0.000 {built-in method numpy.core.multiarray.array}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Time without CProfile: 3.899562120437622
简而言之,使用cProfile测量时,Cythonized代码似乎从13.19秒提高到3.920秒,但使用内置时间进行测量时,改进实际上仅为4.13秒至3.89秒。
Cython确实提供了一些加速(即使天真地使用)但是通过时间分析器测量加速似乎会使结果膨胀。也许这些时间分析器比使用核心代码更有益于使用cython。这是真的还是我做错了什么?
编辑:另外,我不确定为什么在cythonized代码中cIrofile没有跟踪{内置方法math.exp}。
答案 0 :(得分:1)
python配置文件模块docs直接解决此问题
注意探查器模块旨在为给定程序提供执行配置文件,而不是用于基准测试目的(为此,有合理准确结果的时间)。这特别适用于针对C代码对Python代码进行基准测试:分析器引入了Python代码的开销,但不是C级函数的开销,因此C代码似乎比任何Python代码都快。