[英]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.nan
或numpy.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.