使用来自其他 Cython 代码的自定义 Cython 代码
我目前正在尝试优化我的 Python 程序,并开始使用 Cython 以减少函数调用开销,也许稍后会包含优化的 C 库函数。
所以我遇到了第一个问题:
我在代码中使用组合来创建一个更大的类。到目前为止,我已经将我的一个 Python 类转换为 Cython(这已经足够困难了)。代码如下:
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 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 的类型 - 根据为了消除函数调用开销,文档(早期绑定速度)是必要的。我尝试了以下方法,但不起作用:
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
时,我收到此错误:
membraneClass.pyx:18:6: 'bendingForcesClass' is not a type identifier
building 'membraneClass' extension
请注意,声明位于两个单独的文件中,这使得这变得更加困难。
那么我该如何完成这件事呢?如果有人能给我指点,我将非常感激,因为除了上面给出的链接之外,我找不到任何有关此的信息。
谢谢并致以诚挚的问候!
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:
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
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)
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)
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.
Thanks and best regards!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
免责声明:这个问题很老了,我不确定当前的解决方案是否适用于 2011 Cython 代码。
为了从另一个文件导入扩展类(cdef 类),您需要提供 .pxd 文件(也称为定义文件)声明所有 C 类、属性和方法。请参阅文档中的共享扩展类型供参考。
对于您的示例,您需要一个文件
bendingForcesClass.pxd
,它声明您想要共享的类,以及所有 cimport、模块级变量、typedef 等:bendingForcesClass .pxd
所有导入、变量和现在在
.pxd
文件中声明的属性可以(并且必须)从.pyx
文件中删除:bendingForcesClass .pyx
现在您的 cdef 类
bendingForcesClass
可以从其他 Cython 模块导入,使其成为有效的类型标识符,这应该可以解决您的问题。Disclaimer: This question is very old and I am not sure the current solution would work for 2011 Cython code.
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.
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.:bendingForcesClass .pxd
All imports, variables, and attributes that now are declared in the
.pxd
file can (and have to be) removed from the.pyx
file:bendingForcesClass .pyx
Now your cdef class
bendingForcesClass
can be cimported from other Cython modules, making it a valid type identifier, which should solve your problem.您需要使用声明“.pxd”文件和 cimport。 (本质上,cimport 发生在编译时,而 import 发生在运行时,因此 Cython 无法利用任何重要的内容)。
pyx 文件中的所有声明读取到 .pxd 文件中。
// 这里的扩展答案:
Cython:在类型声明中使用导入的类
You need to use a declaration ".pxd" file and cimport. (Essentially, cimport happens at compile time, while import happens at run time so Cython can't make use of anything important).
all declarations which have been in the pyx file go into the .pxd file.
// Extended answer from here:
Cython: using imported class in a type declaration
这些可能不是错误的根源,但为了缩小问题范围,您可以尝试更改以下内容:
是否您在此处使用
bendingForces
作为变量的名称:以及也是此处成员对象的名称:
此外,bendingForcesClass 是模块和类的名称。最后,从类
bendingForcesClass
中创建一个ctypedef
怎么样?These are probably not the source of the error, but just to narrow down the problem, you might try to change the following:
Could it be that you are using
bendingForces
as the name of the variable here:and also the name of the member object here:
Also,
bendingForcesClass
is the name of the module as well as the class. Finally, how about making actypedef
from the classbendingForcesClass
?