我正在尝试编译这种代码:
def my_func(double c, int m):
cdef double f[m][m]
f = [[c for x in range(m)] for y in range(m)]
...
Run Code Online (Sandbox Code Playgroud)
提出:
Error compiling Cython file:
------------------------------------------------------------
def grow(double alpha, double beta, double gamma, int m, int s):
cdef double f[m][m]
^
------------------------------------------------------------
test.pyx:6:22: Not allowed in a constant expression
Run Code Online (Sandbox Code Playgroud)
之后我假设我不能在指向的地方使用变量,我尝试使用数值:
def my_func(double c, int m):
cdef double f[500][500]
f = [[c for x in range(500)] for y in range(500)]
...
Run Code Online (Sandbox Code Playgroud)
但后来我得到:
Error compiling Cython file:
------------------------------------------------------------
f = [[beta for x in range(500)] for y in range(500)]
^
------------------------------------------------------------
test.pyx:13:6: Assignment to non-lvalue 'f'
Run Code Online (Sandbox Code Playgroud)
所以,我想知道如何在cython代码中声明和制作2D列表.我在google搜索"cython 2D list"的文档中找不到这种例子
不要在Cython中使用列表推导.他们创建常规的python列表没有加速.Wiki 说,你应该在Cython中使用动态分配如下:
from libc.stdlib cimport malloc, free
def my_func(double c, int m):
cdef int x
cdef int y
cdef double *my_array = <double *>malloc(m * m * sizeof(double))
try:
for y in range(m):
for x in range(m):
#Row major array access
my_array[ x + y * m ] = c
#do some thing with my_array
finally:
free( my_array )
Run Code Online (Sandbox Code Playgroud)
但是如果你需要一个2D数组的python对象,建议使用NumPy.
小智 7
cdef double f[500][500]
Run Code Online (Sandbox Code Playgroud)
这是宣布500个双打的500 C阵列的C阵列.这是500*500打包的双值(在这种情况下存储在堆栈中,除非Cython做了一些时髦的事情)没有任何间接,这有助于提高性能和缓存利用率,但显然会增加严格的限制.也许你想要这个,但你应该学习足够的C来了解这意味着什么.顺便说一句,一个限制是大小必须是编译时常量(取决于C版本; C99和C10允许它),这是第一个错误消息的内容.
如果您确实使用数组,则不会初始化f您的方式,因为这没有任何意义.f已经是500x500的双变量,并且无法将数组作为一个整体分配给(后者的错误消息试图告诉你).特别是,list comprehension创建了一个完整的Python列表对象(您也可以使用Cython,见下文),其中包含完全成熟的"盒装"Python对象(float在本例中为对象).列表与C数组不兼容.使用for带有项目分配的嵌套循环进行初始化.最后,这样的数组需要500*500*8字节,几乎是2 MiB.在某些系统上,这比整个堆栈大,而在所有其他系统上,它是堆栈的如此大部分,这是一个坏主意.您应该堆分配该数组.
如果您使用Python列表,请注意您在性能和内存使用方面不会得到很大改进(假设您的代码主要是操作该列表),尽管您可能会获得一些回报.你可以放弃cdef,或者list作为类型使用(也object应该工作,但你从中得不到任何东西,所以你也可以省略它).
NumPy阵列可以更快,更节省内存,并且使用起来更方便.如果你能实现与NumPy的操作方面的算法的性能关键部分,你可能会获得所需的加速,而不使用用Cython 可言.