使用其他Cython代码中的自定义Cython代码 [英] Using self-defined Cython code from other Cython code

查看:170
本文介绍了使用其他Cython代码中的自定义Cython代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试优化我的Python程序,并开始使用Cython,以减少函数调用的开销,也许以后还包括优化的C库函数.

I am currently trying to optimize my Python program and got started with Cython in order to reduce the function calling overhead and perhaps later on include optimized C-libraries functions.

所以我遇到了第一个问题:

So I ran into the first problem:

我在代码中使用组合来创建一个更大的类.到目前为止,我已经将我的Python类之一转换为Cython(这很困难).这是代码:

I am using composition in my code to create a larger class. So far I have gotten one of my Python classes converted to Cython (which was difficult enough). Here's the code:

import numpy as np
cimport numpy as np
ctypedef np.float64_t dtype_t
ctypedef np.complex128_t cplxtype_t
ctypedef Py_ssize_t index_t

cdef class bendingForcesClass(object):
    cdef dtype_t bendingRigidity
    cdef np.ndarray matrixPrefactor
    cdef np.ndarray bendingForces

    def __init__(self, dtype_t bendingRigidity, np.ndarray[dtype_t, ndim=2] waveNumbersNorm):
        self.bendingRigidity = bendingRigidity
        self.matrixPrefactor = -self.bendingRigidity * waveNumbersNorm ** 2

    cpdef np.ndarray calculate(self, np.ndarray membraneHeight):
        cdef np.ndarray bendingForces
        bendingForces = self.matrixPrefactor * membraneHeight
        return bendingForces

在我的Python/Cython组合类中,我调用类方法calculate,因此在组合类中,我具有以下(简化的)代码:

From my composed Python/Cython class I am calling the class-method calculate, so that in my composed class I have the following (reduced) code:

from bendingForcesClass import bendingForcesClass

cdef class membraneClass(object):
    def  __init__(self, systemSideLength, lowerCutoffLength, bendingRigidity):
        self.bendingForces = bendingForcesClass(bendingRigidity, self.waveNumbers.norm)

    def calculateForces(self, heightR):
        return self.bendingForces.calculate(heightR)

我发现cpdef使方法/函数可以从Python和Cython调用,这很好并且可以工作,只要我不尝试预先定义self.bendingForces的类型-根据<要消除函数调用的开销,必须使用href ="https://github.com/cython/cython/wiki/EarlyBindingForSpeed" rel ="noreferrer">文档(提早绑定).我已经尝试了以下方法,但不起作用:

I have found out that cpdef makes the method/functions callable from Python and Cython, which is great and works, as long as I don't try to define the type of self.bendingForces beforehand - which according to the documentation (Early Binding For Speed) is necessary in order to remove the function-calling overhead. I have tried the following, which does not work:

from bendingForcesClass import bendingForcesClass
from bendingForcesClass cimport bendingForcesClass

    cdef class membraneClass(object):
        cdef bendingForcesClass bendingForces

        def  __init__(self, systemSideLength, lowerCutoffLength, bendingRigidity):
            self.bendingForces = bendingForcesClass(bendingRigidity, self.waveNumbers.norm)

        def calculateForces(self, heightR):
            return self.bendingForces.calculate(heightR)

与此有关,当我尝试使用Cython构建membraneClass.pyx时,出现此错误:

With this I get this error, when trying to build membraneClass.pyx with Cython:

membraneClass.pyx:18:6: 'bendingForcesClass' is not a type identifier
building 'membraneClass' extension

请注意,声明位于两个单独的文件中,这使此操作更加困难.

Note that the declarations are in two separate files, which makes this more difficult.

那么我该如何完成呢?如果有人能给我一个指针,我将非常感激,因为除了上面给出的链接之外,我找不到关于此的任何信息.

So I how do I get this done? I would be very thankful if someone could give me a pointer, as I can't find any information about this, besides the link given above.

感谢和问候!

推荐答案

免责声明:这个问题已经很久了,我不确定当前的解决方案是否适用于2011 Cython代码.

Disclaimer: This question is very old and I am not sure the current solution would work for 2011 Cython code.

为了从另一个文件导入扩展类(cdef类),您需要提供一个.pxd 文件(也称为定义文件),用于声明所有C类,属性和方法.请参阅文档中的共享扩展类型供参考.

In order to cimport an extension class (cdef class) from another file you need to provide a .pxd file (also known as a definitions file) declaring all C classes, attributes and methods. See Sharing Extension Types in the documentation for reference.

对于您的示例,您需要一个文件bendingForcesClass.pxd,该文件声明要共享的类,以及所有cimport,模块级变量,typedef等:

For your example, you would need a file bendingForcesClass.pxd, which declares the class you want to share, as well as all cimports, module level variables, typedefs, etc.:

# cimports
cimport numpy as np

# typedefy you want to share
ctypedef np.float64_t dtype_t
ctypedef np.complex128_t cplxtype_t
ctypedef Py_ssize_t index_t

cdef class bendingForcesClass:
    # declare C attributes
    cdef dtype_t bendingRigidity
    cdef np.ndarray matrixPrefactor
    cdef np.ndarray bendingForces

    # declare C functions
    cpdef np.ndarray calculate(self, np.ndarray membraneHeight)

    # note that __init__ is missing, it is not a C (cdef) function

现在可以(必须)从.pyx文件中删除在.pxd文件中声明的所有导入,变量和属性:

All imports, variables, and attributes that now are declared in the .pxd file can (and have to be) removed from the .pyx file:

import numpy as np

cdef class bendingForcesClass(object):

    def __init__(self, dtype_t bendingRigidity, np.ndarray[dtype_t, ndim=2] waveNumbersNorm):
        self.bendingRigidity = bendingRigidity
        self.matrixPrefactor = -self.bendingRigidity * waveNumbersNorm ** 2

    cpdef np.ndarray calculate(self, np.ndarray membraneHeight):
        cdef np.ndarray bendingForces
        bendingForces = self.matrixPrefactor * membraneHeight
        return bendingForces

现在可以从其他Cython模块中导入cdef类bendingForcesClass,使其成为有效的类型标识符,这应该可以解决您的问题.

Now your cdef class bendingForcesClass can be cimported from other Cython modules, making it a valid type identifier, which should solve your problem.

这篇关于使用其他Cython代码中的自定义Cython代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆