Cython在基本求和计算方面并不比Python快多少



我试图遵循Continuum Analytics博客上给出的一个例子,对Python、Cython和Numba进行基准测试,以获得使用for循环计算的总和。不幸的是,我发现Cython比Python慢!

以下是我的Python函数定义:

def python_sum(y):
N = len(y)
x = y[0]
for i in xrange(1,N):
x += y[i]
return x

现在我的Cython函数:

def cython_sum(int[:] y):
cdef int N = y.shape[0]
cdef int x = y[0]
cdef int i
for i in xrange(1,N):
x += y[i]
return x

现在我有了一个脚本,它提取了两个函数和基准:

import timeit
import numpy as np
import cython_sum
import python_sum
b = np.ones(10000)
timer = timeit.Timer(stmt='python_sum.python_sum(b)', setup='from __main__ import python_sum, b')
print "Python Sum    (ms): %g" % (timer.timeit(1)*1000)
timer = timeit.Timer(stmt='cython_sum.cython_sum(b)', setup='from __main__ import cython_sum, b')
print "Cython     (ms): %g" % (timer.timeit(1)*1000)

现在我的输出是:

Python Sum    (ms): 9.44624
Cython     (ms): 8.54868

根据上面链接的博客文章中的图表,我预计速度会提高100倍到1000倍,但我所看到的只是Cython比普通Python稍微快一点。

我是不是做错了什么?这似乎是一个非常基本的问题,有一个简单的函数定义,很明显,很多人都非常成功地使用了Cython,所以很明显,错误一定在我身上。有人能阐明这一点并告诉我我做错了什么吗?非常感谢。

我不知道你为什么会得到这样的结果。正如一位评论者所说,你的代码本来就不应该工作,因为你会把floats传递到一个期望ints的函数中。也许你把一个cython_sum.py文件放在了同一个目录中?

我做了以下事情。我创建了一个python_sum.py,其中包含您对python_sum的确切定义。然后我稍微更改了你的Cython代码:

cython_sum.pyx

def cython_sum(long[:] y):    #changed `int` to `long`
cdef int N = y.shape[0]
cdef int x = y[0]
cdef int i
for i in xrange(1,N):
x += y[i]
return x

我制作了一个能够构建Cython模块的设置文件:

设置.py

from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Cython sum test',
ext_modules = cythonize("cython_sum.pyx"),
)

我使用python setup.py build_ext --inplace构建了模块。接下来,我运行了一些修改后的测试代码:

测试.py

import timeit
import numpy as np
import cython_sum
import python_sum
# ** added dtype=np.int to create integers **
b = np.ones(10000, dtype=np.int)    
# ** changed .timeit(1) to .timeit(1000) for each one **
timer = timeit.Timer(stmt='python_sum.python_sum(b)', setup='from __main__ import python_sum, b')
print "Python Sum    (ms): %g" % (timer.timeit(1000)*1000)
timer = timeit.Timer(stmt='cython_sum.cython_sum(b)', setup='from __main__ import cython_sum, b')
print "Cython        (ms): %g" % (timer.timeit(1000)*1000)

我得到了以下结果:

$ python test.py
Python Sum    (ms): 4111.74
Cython        (ms): 7.06697

现在这是一个很好的加速!


此外,通过遵循此处概述的指导方针,我能够获得额外的(小)加速:

cython_fastrongum.pyx

import numpy as np
cimport numpy as np
DTYPE = np.int
ctypedef np.int_t DTYPE_t
def cython_sum(np.ndarray[DTYPE_t, ndim=1] y):
cdef int N = y.shape[0]
cdef int x = y[0]
cdef int i
for i in xrange(1,N):
x += y[i]
return x

setup_fast.py

from distutils.core import setup
from Cython.Build import cythonize
import numpy as np
setup(
name = 'Cython fast sum test',
ext_modules = cythonize("cython_fast_sum.pyx"),
include_dirs = [np.get_include()],
)

测试.py

import timeit
import numpy as np
import cython_sum
import cython_fast_sum
b = np.ones(10000, dtype=np.int)
# ** note 100000 runs, not 1000 **
timer = timeit.Timer(stmt='cython_sum.cython_sum(b)', setup='from __main__ import cython_sum, b')
print "Cython naive  (ms): %g" % (timer.timeit(100000)*1000)
timer = timeit.Timer(stmt='cython_fast_sum.cython_sum(b)', setup='from __main__ import cython_fast_sum, b')
print "Cython fast   (ms): %g" % (timer.timeit(100000)*1000)

结果:

$ python test.py
Cython naive  (ms): 676.437
Cython fast   (ms): 645.797

最新更新