簡體   English   中英

Cython:使用融合類型在一個參數中傳遞多個numpy數組

[英]Cython: Passing multiple numpy arrays in one argument with fused types

我已經重寫了從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")

我意識到我可以在元組中指定類型,但如果我理解正確的話,沒有比“對象”更復雜的東西。 有誰知道我正在做的事情更清潔的方式? 任何其他cython技巧表示贊賞。

傳遞了其他參數,包括與數組相同類型的fill_value參數。 如果test_dtype可以在調用時通過數組或fill參數確定,代碼會變test_dtype簡單,但我找不到一個好的方法來保證C將以正確的類型接收值。 例如,傳遞numpy.nannumpy.float64(numpy.nan)並不保證數據類型。

在Python和NumPy編程10年之后(以及C,C ++,Matlab和Fortran之前10年),這是我的總體印象:

使用C語言編寫C,C ++或Fortran中的數字代碼通常比使用Cython更容易。 我能想到的唯一例外是最小的代碼snipplet。 在C ++中,您可以使用模板和STL(如果您願意,還可以使用Boost)。

學習使用NumPy C API。 PyArrayObject(在C中調用NumPy數組)具有可用於調度的類型編號。 您可以使用PyArrayObject *上的宏PyArray_TYPE()獲取它。 numpy.float64映射到類型號NPY_FLOAT64,numpy.float32映射到類型號NPY_FLOAT32等。然后你有相應的C和C ++ typedef,你可以在你的C或C ++代碼中使用:如果PyArray_TYPE(x)== NPY_FLOAT64,數據要在C或C ++中使用的類型是npy_float64。 這樣您就可以編寫C或C ++代碼,這些代碼完全由您傳入的NumPy數組定義。

我通常在PyArray_TYPE(x)上使用switch語句,在NPY_FLOAT64,NPY_FLOAT32等上使用case。對於每種情況,我都使用正確的模板類型調用模板化C ++函數。 這樣可以將我需要寫入的代碼量保持在最低限度。

http://docs.scipy.org/doc/numpy/reference/c-api.html

Cython適用於包裝C和C ++並避免繁瑣的Python C API編碼,但這是對靜態類型參數的限制。 對於“從頭到尾”的數字代碼,我認為使用普通的C ++會更好,但Cython是一個很好的工具,可以將它暴露給Python。 所以用C ++編寫你的數字內容並使用Cython來調用你的C ++。 這將是我能給出的最佳建議.Cython是編寫Python擴展的優秀工具,但當C ++是您真正想要的時候,它不能替代C ++。

至於你的問題:你想做的事情真的不可能。 因為在C或C ++中,這是Cython發出的,numpy.ndarray是PyArrayObject *,無論dtype如何。 所以你需要手動編寫switch語句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM