Python Cython:使用融合类型在一个参数中传递多个numpy数组

Python Cython:使用融合类型在一个参数中传递多个numpy数组,python,numpy,cython,Python,Numpy,Cython,我已经将一个算法从C重写为Cython,因此我可以利用融合类型,并使从python调用更容易。该算法可以处理多个数组以及其他一些参数。数组被接受为指向指针的指针(例如)。我想我可以通过将多个数组作为numpy数组的元组来调用python中的cython代码,但这样做会让融合类型变得有点混乱。下面是一个简单的示例,说明我现在是如何使用它的: import numpy cimport numpy ctypedef fused test_dtype: numpy.float32_t

我已经将一个算法从C重写为Cython,因此我可以利用融合类型,并使从python调用更容易。该算法可以处理多个数组以及其他一些参数。数组被接受为指向指针的指针(例如)。我想我可以通过将多个数组作为numpy数组的元组来调用python中的cython代码,但这样做会让融合类型变得有点混乱。下面是一个简单的示例,说明我现在是如何使用它的:

import numpy
cimport numpy

ctypedef fused test_dtype:
    numpy.float32_t
    numpy.float64_t

cdef int do_stuff(test_dtype **some_arrays):
    if test_dtype is numpy.float32_t:
        return 1
    elif test_dtype is numpy.float64_t:
        return 2
    else:
        return -1

def call_do_stuff(tuple some_arrays):
    cdef unsigned int num_items = len(some_arrays)
    cdef void **the_pointer = <void **>malloc(num_items * sizeof(void *))
    if not the_pointer:
        raise MemoryError("Could not allocate memory")
    cdef unsigned int i
    cdef numpy.ndarray[numpy.float32_t, ndim=2] tmp_arr32
    cdef numpy.ndarray[numpy.float64_t, ndim=2] tmp_arr64
    if some_arrays[0].dtype == numpy.float32:
        for i in range(num_items):
            tmp_arr32 = some_arrays[i]
            the_pointer[i] = &tmp_arr32[0, 0]
        return do_stuff(<numpy.float32_t **>the_pointer)
    elif some_arrays[0].dtype == numpy.float64:
        for i in range(num_items):
            tmp_arr64 = some_arrays[i]
            the_pointer[i] = &tmp_arr64[0, 0]
        return do_stuff(<numpy.float64_t **>cols_pointer)
    else:
        raise ValueError("Array data type is unknown")
导入numpy
纽比港
ctypedef保险丝测试\u数据类型:
numpy.float32\u t
numpy.float64\u t
cdef int do_stuff(测试数据类型**一些数组):
如果测试类型为numpy.float32\u t:
返回1
elif测试类型为numpy.float64\t:
返回2
其他:
返回-1
def call_do_stuff(一些数组的元组):
cdef unsigned int num_items=len(某些_数组)
cdef void**指针=malloc(num\u items*sizeof(void*))
如果不是_指针:
raise MemoryError(“无法分配内存”)
无符号整数i
cdef numpy.ndarray[numpy.float32_t,ndim=2]tmp_arr32
cdef numpy.ndarray[numpy.float64_t,ndim=2]tmp_arr64
如果某些_数组[0].dtype==numpy.float32:
对于范围内的i(num_项):
tmp_arr32=一些_数组[i]
_指针[i]=&tmp_arr32[0,0]
返回do_stuff(_指针)
elif某些_数组[0]。dtype==numpy.float64:
对于范围内的i(num_项):
tmp_arr64=一些_数组[i]
_指针[i]=&tmp_arr64[0,0]
返回do_stuff(cols_指针)
其他:
raise VALUERROR(“数组数据类型未知”)
我意识到我可以在元组中指定类型,但是如果我理解正确,没有什么比“object”更复杂的了。有人知道我要做的事有没有更干净的方法?任何其他cython提示都将不胜感激


传递的其他参数包括与数组类型相同的
fill\u值
参数。如果
test\u dtype
可以在调用时通过数组或fill参数来确定,那么代码会变得更简单,但是我找不到一个好方法来保证C将接收正确类型的值。例如,通过<代码> Nopy.No.No/C>或<代码> NoMPy .ForUAT64(NoPpy.Nan)不能保证数据类型。

P>在编程Python和NuMPy 10年之后(C、C++、Matlab和FORTRAN之前10年),这是我的总体印象:

在C、C++或FORTRAN中编写Cython代码比Cython更容易。我能想到的唯一例外是最小的代码片段。在C++中,你可以使用模板和STL(如果你喜欢的话,也可以升压)。 学习使用NumPy C API。PyArrayObject(在C中称为NumPy数组)有一个可用于分派的类型号。您可以在PyArrayObject*上使用宏PyArray_TYPE()获得它。NoPy.FulAT64映射到NPyIOFLAT64、NUPYP.FLUAT32映射到NPYIORATAT32等类型,然后您可以在C或C++代码中使用相应的C和C++类型DEPs:如果PyRayayType(x)=NPyIOFLAT64,在C或C++中使用的数据类型是NPYYFLAUT64。通过这种方式,你可以编写C或C++代码,这些代码完全由你传递的NUPY数组定义。p>

我通常在PyRayayType(x)上使用一个开关语句,并且使用NPyIOFLATAT64、NPYIOFLAT32等来进行调用。对于每种情况,我都调用模板化的C++函数,并具有正确的模板类型。这使我需要写的代码量保持在最低限度

Cython是封装C和C++的好工具,避免冗长的Python C API编码,但这里限制了静态类型参数的大小。对于“下至铁”的数字代码,我认为使用纯C++更好,但是Cython是一种将其暴露到Python的极好工具。所以用C++编写你的数字资料,并使用Cython来调用C++。这是我能给出的最好的建议,Cython是一个优秀的工具,用于编写Python的C扩展,但是它不是C++的替代,而C++是你真正想要的。


至于你的问题:你想做的事情实际上是不可能的。因为在C或C++中,这是Cython发出的,NyPy.nDARRY是PyRayAbjy*,不管DyType。因此,您需要手工编写switch语句。

很有意义。我曾考虑过直接用C/C++编写代码的主要部分,但我认为我应该学习cython,以便将来可能的项目使用。我正在使用的代码的实际工作部分是