我想加速一个我经常使用的函数,我想用cython。然而,在尝试了我在文档中找到的所有可能的cython优化之后,cython代码大约比python+numpy函数慢6倍。令人失望!在
这是我的测试代码:(forward1是python函数,forward2是cython函数)
#geometry.py
def forward1(points, rotation, translation):
'''points are in columns'''
return np.dot(rotation, points - translation[:, np.newaxis])
#geometry.pyx
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cdef np.float64_t[:,:] forward2(np.float64_t[:,:] points, np.float64_t[:,:] rotation, np.float64_t[:] translation):
'''points are in columns'''
cdef unsigned int I, J
I = points.shape[0]
J = points.shape[1]
cdef np.float64_t[:,:] tmp = np.empty((I, J), dtype=np.float64)
cdef unsigned int i
for i in range(J):
tmp[0, i] = points[0, i] - translation[0]
tmp[1, i] = points[1, i] - translation[1]
cdef np.float64_t[:,:] result = np.dot(rotation, tmp)
return result
def test_forward2(points, rotation, translation):
import timeit
cdef np.float64_t[:,:] points2 = points
cdef np.float64_t[:,:] rotation2 = rotation
cdef np.float64_t[:] translation2 = translation
t = timeit.Timer(lambda: forward2(points2, rotation2, translation2))
print min(t.repeat(3, 10))
然后我计时:
^{pr2}$我能做些什么让cython代码更快些吗?在
如果forward1在cython中不能加速,我能用weave来加速吗?在
编辑:
我想说的是,另一件我试图加快函数速度的事情是按fortran顺序传递点,因为我的点存储在列中,而且其中有很多列。我还将本地tmp定义为fortran顺序。我认为函数的减法部分应该更快,但是纽比.dot似乎需要一个C命令输出(无论如何要解决这个问题?),所以这也没有加速。我还试着转置这些点,这样减法部分在C顺序中更快,但看起来点积仍然是最昂贵的部分。在
我也注意到了纽比.dot不能使用memoryviews作为out参数,即使它是C命令,这是一个bug吗?在
只要浏览一下您的代码,它看起来像是
numpy
已经非常适合的东西(数组和点积的减法)。在Cython非常适合于加速numpy通常执行不佳的情况(例如迭代算法是用python编写的),但是在这种情况下,内部循环已经由BLAS库执行了。在
如果你想加快速度,我首先要看的是BLAS/LAPACK/ATLAS/etc库与numpy的链接。在这种情况下,使用“调优”的线性代数库(如ATLAS或Intel的MKL)会产生很大的不同(在某些情况下,甚至是10倍)。在
要了解您当前使用的是什么,请查看
numpy.show_config()
的输出相关问题 更多 >
编程相关推荐