【问题标题】:Cython, pure Python mode: .pxd and @localsCython,纯 Python 模式:.pxd 和 @locals
【发布时间】:2014-07-10 04:14:44
【问题描述】:

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

提前感谢您的帮助。

【问题讨论】:

    标签: python cython


    【解决方案1】:

    最后,我从 Cython 的 Google Groups 官方论坛获得了帮助。如果写一个.pyx文件,.pxd只是为了和其他模块共享函数定义;特别是,它不会增强原始功能,并且上面的所有三个示例都没有从编译原始 python 脚本中添加任何内容。

    虽然可以将 .pxd 与原始 .py 结合使用,以修复简单函数和类属性的可变类型,但它有很多限制。

    @cython.locals 不允许触摸类属性,而只能触摸(非xxx)函数参数。在这种特殊情况下它不会做任何事情。总的来说,我认为这些装饰器不是正确的方法。

    最好的方法可能是在公共模式下用 .pyx 中的 Cython 语法重写一些函数(“cpdef”创建一个 Python 包装器),编译它,然后将函数/类导入Python 代码与其他库一样。但它不再是真正的纯 Python。

    【讨论】:

    • 能否请您链接到 Google 网上论坛的讨论?谢谢!
    【解决方案2】:

    关于您的@cython.locals,我认为您应该尝试将它放在__init__ 方法之前,而不是在类声明之前,因为它指的是构造函数。

    考虑使用@cython.cclass 来声明cdef 类。

    要修复变量的类型,请使用cython.declare()@cython.locals,请参阅magic attributes

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

    另一种方法是将您的代码作为纯 python 保存在 .py 文件中,并使用具有相同名称的扩充 .pxd 文件。 python 代码看起来会更干净,但维护单独的.pxd 文件可能需要更长的时间。请参阅this 部分。这基本上就是您在上一个示例中所做的。

    【讨论】:

    • 我知道创建一个cdef 类可以使我的类在C 端可用,但是由于它已经按原样编译,有兴趣在这里使用@cython.cclass 吗?我浏览了官方文档十几次,仍然不明白我在做什么......
    • 是的,它应该运行得更快。阅读有关 cdef 类的页面,link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    相关资源
    最近更新 更多