我是Cython的新手,在浏览Cython文档后,我遇到了Cython Extention types 。我想知道它对普通Python类有什么好处?我试图将我之前在其数据成员中具有列表的Python类转换为Cython扩展类型,但似乎我不能将列表声明为扩展类型中的数据成员。我唯一能做的就是将使用原始C数据类型的数据成员的Python类转换为Cython扩展类型。
我在Python类中有一段代码需要使用Cython进行优化。如何在不将类声明为Cython扩展类型的情况下Cython化与该段相关的函数? (基本上我只想将某些函数声明为cdef,而不是全部。)
答案 0 :(得分:2)
在Cython中编写代码时,我没有使用过那些cdef
ed类,所以我会将这部分留给cdef
ed类型的好处让其他人回答。
在列表方面,虽然您仍然可以正常使用Python列表,但您需要copy each member explicitly into a C array来充分利用C语言编写的加速功能。但是,如果数据存储在一个NumPy数组,你可以只存储一个指向数组开头的指针(确保数组是C-连续的)。可以在此处找到NumPy和C类型的完整等价表:https://github.com/cython/cython/blob/master/Cython/Includes/numpy/__init__.pxd
至于cythonising类方法,因为大多数Python代码可以在Cython中无需修改就可以正常工作,你可以像往常一样使用class SomeClass:
在Cython中定义你的类。由于cdef
函数只能在Cython中调用,因此您可能希望在类外部定义cython化方法(最好键入以提高性能)。在类中,您可以使用常规def
(可以从Python调用)来调用它们的cythonised对应项。
对于较大的Python类,你不想进入Cython,你可以使用类似的方法,但在Cython中只有def
ed函数调用cdef
ed版本。然后,您可以像导入模块时通常那样从Python调用Cython函数。
对于只需要驻留在C中而不与Python交互的数据结构,您可能还需要考虑使用PyCapsule将它们存储为类属性。
修改强>
通过阅读 chrisb 的答案下的评论,我认为你想拥有一个可变行长的二维数组。在深入研究在C中实现完全相同的数据结构之前,值得注意的是C不是Python。它不会自动为您管理列表的长度,而是您必须自己管理内存(请参阅第一个链接中的示例)。虽然这是动态分配内存的标准方式,但C(和Cython)新手的程序员往往不想触摸" malloc
和朋友"因为指针会飞来飞去。最重要的是,C阵列通常没有混合数据类型,例如,你不能在同一个数组中同时包含数字和字符串(如果真的需要,有一种方法可以做到这一点。)
鉴于此,您可能希望重新考虑您的数据结构。例如,您可以考虑使用常量长度的数组来表示数据。如果您的阵列具有最大宽度,则可以使用NumPy阵列轻松编程来交换内存。
如果您乐意尝试手动内存管理,这里有一个为int
的2D数组分配内存的简单示例:
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
cdef int **generate_2D_array(int rows, int columns):
cdef int row
cdef int **parent = <int **>PyMem_Malloc(rows * sizeof(int*))
if not parent:
raise MemoryError()
for row in range(rows):
parent[row] = <int *>PyMem_Malloc(columns * sizeof(int))
if not parent[row]:
raise MemoryError()
return parent
要更改行的长度,您可以使用:
cdef void resize_row(int *row_pointer, int new_size):
PyMem_Realloc(row_pointer, new_size)
完成数据后,请记住使用PyMem_Free
以与PyMem_Malloc
分配类似的方式释放内存。经验法则是:对于您使用的每个PyMem_Malloc
,只使用一个PyMem_Free
释放内存,不多也不少。最后,只是一句警告,未能正确使用这些可能会导致分段错误,内存泄漏或未定义的行为。
答案 1 :(得分:0)
对于python-heavy操作,由于优化的字段访问和python开销删除,cdef类仍然会有一些性能优势。简单的例子:
0
这是以简单/调试能力为代价的,因此可能值得也可能不值得。更好的用例是当你想要存储和使用某些c级值时,性能优势可能会更加显着。