如何在Cython中声明2D列表

我正在尝试编译这种代码:

def my_func(double c, int m):
    cdef double f[m][m]

    f = [[c for x in range(m)] for y in range(m)]
    ...

提出:

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

之后我假设我不能在指向的地方使用变量,我尝试使用数值:

def my_func(double c, int m):
    cdef double f[500][500]

    f = [[c for x in range(500)] for y in range(500)]
    ...

但后来我得到:

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'

所以,我想知道如何在cython代码中声明和制作2D列表.我在google搜索“cython 2D list”的文档中找不到这种例子

最佳答案
cdef double f[500][500]

这是宣布500个双打的500 C阵列的C阵列.这是500 * 500打包的双值(在这种情况下存储在堆栈中,除非Cython做了一些时髦的事情),没有任何间接,这有助于提高性能和缓存利用率,但显然会增加严格的限制.也许你想要这个,但你应该学习足够的C来了解这意味着什么.顺便说一句,一个限制是大小必须是编译时常量(取决于C版本; C99和C10允许它),这是第一个错误消息的内容.

如果您确实使用数组,则不会按照您的方式初始化f,因为这没有任何意义. f已经是500×500双变量,并且整个数组无法分配(这是后一个错误消息试图告诉你的).特别是,list comprehension创建了一个完整的Python列表对象(您也可以在Cython中使用,见下文),其中包含完全成熟的“盒装”Python对象(在本例中为float对象).列表与C数组不兼容.使用嵌套for循环和项目分配进行初始化.最后,这样的数组需要500 * 500 * 8字节,几乎是2 MiB.在某些系统上,这比整个堆栈大,而在所有其他系统上,它是堆栈的如此大部分,这是一个坏主意.您应该堆分配该数组.

如果您使用Python列表,请注意您在性能和内存使用方面不会得到很大改进(假设您的代码主要是操作该列表),尽管您可能会获得一些回报.你可以放弃cdef,或者使用list作为类型(对象也应该工作,但是你没有从中获得任何东西,所以你也可以省略它).

NumPy阵列可以更快,更节省内存,并且使用起来更方便.如果您可以根据NumPy的操作实现算法的性能关键部分,则可以在不使用Cython的情况下获得所需的加速.

转载注明原文:如何在Cython中声明2D列表 - 代码日志