Cython,纯Python模式: .pxd和@locals

4 投票
2 回答
2373 浏览
提问于 2025-04-18 07:12

我有一个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 个回答

2

关于你的 @cython.locals,我觉得你应该把它放在 __init__ 方法之前,而不是类声明之前,因为它是指构造函数的。

可以考虑使用 @cython.cclass 来声明一个 cdef 类。

要修复一个变量的类型,可以使用 cython.declare()@cython.locals,具体可以查看 魔法属性

以上选项必须包含在 .py.pyx 文件中,这些都是特殊的 cython 函数和/或装饰器。

另一种选择是把你的代码保留在一个 .py 文件中,作为纯 Python 代码,并使用一个同名的 .pxd 文件来增强功能。这样 Python 代码看起来会更简洁,但维护这个单独的 .pxd 文件可能会花更多时间。可以查看 这一部分。这基本上就是你在最后一个例子中所做的。

0

最后,我在Google Groups的Cython官方论坛得到了帮助。如果你写一个.pyx文件,.pxd文件只是用来和其他模块分享函数定义的;特别是,它不会增强原来的函数,上面提到的三个例子在编译原始的Python脚本时并没有增加任何东西。

不过,你可以把.pxd和一个普通的.py文件一起使用,这样可以修正简单函数和类属性的变量类型,但它有很多限制。

@cython.locals不允许修改类属性,只能处理(非xxx)函数的参数。在这种情况下,它是没有用的。总的来说,我觉得这些装饰器不是正确的方法。

最好的办法可能是用Cython的语法重写一些函数,放在一个.pyx文件中,使用公共模式(“cpdef”会创建一个Python包装),编译它,然后像使用其他库一样把函数/类导入到Python代码中。但这样就不完全是纯Python了。

撰写回答