Cython,纯Python模式: .pxd和@locals
我有一个Python程序,想用Cython来加速,同时保持源代码可以被Python解释器读取(也就是“纯Python模式”)。光是编译它,我就得到了20%的速度提升。接着,我创建了一个.pxd文件,并在我的.pyx脚本中添加了一些“@cython.locals(...)”来指定变量的类型。但是在添加这两个功能之前和之后,我运行的时间没有看到任何变化。
所以我有三个类似的问题:
首先,我在我的.pyx文件中添加了:
@cython.locals(start=cython.int, end=cython.int)
class C(object):
def __init__(self, start, end)
self.start = start
self.end = end
这样做真的有用吗?
其次,如果我的.pyx中有一个类:
class Counter(object):
def __init__(self):
self.n = 0
def __call__(self, x):
self.n += 1
有没有什么办法可以指定“n”的类型(就像在“cdef class”后面写“cdef int n”那样)?
最后,如果我的.pyx中有一个函数:
def count():
<do something with variables a,b,c>
在.pxd文件中写以下内容会有什么变化吗?:
cpdef inline count():
cdef:
int a
int b
int c
提前感谢你的帮助。
2 个回答
关于你的 @cython.locals
,我觉得你应该把它放在 __init__
方法之前,而不是类声明之前,因为它是指构造函数的。
可以考虑使用 @cython.cclass
来声明一个 cdef
类。
要修复一个变量的类型,可以使用 cython.declare()
或 @cython.locals
,具体可以查看 魔法属性。
以上选项必须包含在 .py
或 .pyx
文件中,这些都是特殊的 cython 函数和/或装饰器。
另一种选择是把你的代码保留在一个 .py
文件中,作为纯 Python 代码,并使用一个同名的 .pxd
文件来增强功能。这样 Python 代码看起来会更简洁,但维护这个单独的 .pxd
文件可能会花更多时间。可以查看 这一部分。这基本上就是你在最后一个例子中所做的。
最后,我在Google Groups的Cython官方论坛得到了帮助。如果你写一个.pyx文件,.pxd文件只是用来和其他模块分享函数定义的;特别是,它不会增强原来的函数,上面提到的三个例子在编译原始的Python脚本时并没有增加任何东西。
不过,你可以把.pxd和一个普通的.py文件一起使用,这样可以修正简单函数和类属性的变量类型,但它有很多限制。
@cython.locals不允许修改类属性,只能处理(非xxx)函数的参数。在这种情况下,它是没有用的。总的来说,我觉得这些装饰器不是正确的方法。
最好的办法可能是用Cython的语法重写一些函数,放在一个.pyx文件中,使用公共模式(“cpdef”会创建一个Python包装),编译它,然后像使用其他库一样把函数/类导入到Python代码中。但这样就不完全是纯Python了。