如何在Cython中动态声明2D c数组 [英] How to declare 2D c-arrays dynamically in Cython

查看:70
本文介绍了如何在Cython中动态声明2D c数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用各种大小的2D numpy数组执行大量工作,我想将这些计算工作转移到cython上.我的想法是将我的2D numpy数组从python传递到cython,然后将其转换为c数组或内存视图,并用在其他c级函数的级联中进行计算.

I need to perform a lot of work using 2D numpy arrays of various sizes and I would like to offload these calculations onto cython. The idea is that my 2D numpy arrays would be passed from python to cython where it would be converted into c-array or memory view and used in a cascade of other c-level functions to do the calculations.

经过一些分析后,由于一些严重的python开销,我排除了在cython中使用numpy数组的可能性.使用内存视图的速度更快且非常易于使用,但是我怀疑我可以从使用c数组中获得更大的加速.

After some profiling I ruled out using numpy arrays in cython due to some serious python overhead. Using memory views was MUCH faster and quite easy to use, but I suspect I can squeeze even more speedup from using c-arrays.

这是我的问题-如何在cython中声明2D c数组而不用设置值预定义其尺寸?例如,我可以通过以下方式从numpy创建一个c数组:

Here is my question though - how can I declare a 2D c-array in cython without predefining its dimensions with set values? For example, I can create a c-array from numpy this way:

narr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]], dtype=np.dtype("i"))

cdef int c_arr[3][4]:
for i in range(3):
    for j in range(4):
        c_arr[i][j] = narr[i][j]

,然后将其传递给函数:

and then pass it to a function:

cdef void somefunction(int c_Arr[3][4]):
    ...

但这意味着我有一个固定的数组sizde,对我而言这将是无用的.所以我尝试了这样的事情:

But this implies I have a fixed sizde of array, which in my case will be useless. So I tried something like this:

narr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]], dtype=np.dtype("i"))

cdef int a = np.shape(narr)[0]
cdef int b = np.shape(narr)[1]

cdef int c_arr[a][b]:               # INCORRECT - EXAMPLE ONLY

for i in range(a):
    for j in range(b):
        c_arr[i][j] = narr[i][j]

旨在将其传递给这样的函数:

with the intention to pass it to a function like this:

cdef void somefunction(int a, int b, int c_Arr[a][b]):
    ...

但是它不起作用,并且编译失败,并显示错误在常量表达式中不允许".我怀疑我不需要以某种方式使用malloc/free吗?我看过这个问题(如何在Cython中声明2D列表),但无法解决我的问题.

But it doesn't work and the compilation fails with the error "Not allowed in a constant expression". I suspect I need t do it with malloc/free somehow? I had a look at this problem (How to declare 2D list in Cython), but it does not provide the answer to my problem.

事实证明,如果确保为内存视图关闭cython中的indexError检查,则内存视图可以与c数组一样快,这可以通过使用cython编译器指令来完成:

It turns out that memory-views can be as fast as c-arrays if one makes sure that indexError checking in cython is switched-off for the memory views, which can be done by using cython compiler directive:

# cython: boundscheck=False

感谢@Veedrac的提示!

Thanks @Veedrac for the tip!

推荐答案

您只需要停止进行边界检查:

You just need to stop doing bounds checking:

with cython.boundscheck(False):
    thesum += x_view[i,j]

基本上可以使速度达到标准水平.

that brings the speed basically up to par.

如果您真的想要一个C数组,请尝试:

If you really want a C array from it, try:

import numpy as numpy
from numpy import int32
from numpy cimport int32_t

numpy_array = numpy.array([[]], dtype=int32)

cdef:
    int32_t[:, :] cython_view = numpy_array
    int32_t *c_integers_array = &cython_view[0, 0]
    int32_t[4] *c_2d_array = <int32_t[4] *>c_integers_array

首先,您将获得一个Numpy数组.您可以使用它来获取内存视图.然后,您将获得一个指向其数据的指针,并将其转换为所需步幅的指针.

First you get a Numpy array. You use that to get a memory view. Then you get a pointer to its data, which you cast to pointers of the desired stride.

这篇关于如何在Cython中动态声明2D c数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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