2015-01-02 56 views
4

我已經重寫了一個從C到Cython的算法,所以我可以利用融合類型並使得從python調用變得更容易。該算法可以使多個數組與其他一些參數一起工作。數組被接受爲指向指針的指針(例如)。我想我會通過提供多個數組作爲numpy數組的元組來調用python的cython代碼,但要做到這一點與融合類型有點混亂。下面是我怎麼會有現在的工作一個簡單的例子:Cython:通過融合類型在一個參數中傳遞多個numpy數組

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參數確定,代碼會變得更簡單,但我找不到保證C會以正確類型接收值的好方法。例如,通過numpy.nannumpy.float64(numpy.nan)不保證數據類型。

它往往是更容易在C,C寫的數字代碼++或:

回答

5

編程Python和NumPy的10年(和C,C++,MATLAB和Fortran前10年),這是我的總體印象後Fortran比Cython。我能想到的唯一例外是最小的代碼snipplets。在C++中,您可以使用模板和STL(如果您喜歡,還可以使用Boost)。

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

我通常在PyArray_TYPE(x)和NPY_FLOAT64,NPY_FLOAT32等情況下使用switch語句。對於每種情況,我使用正確的模板類型調用模板化的C++函數。這將我需要的代碼量減少到最小。

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

用Cython是良好的包裹C和C++,避免繁瑣的Python C API編碼,但這裏是多少,你可以靜態類型參數的限制。對於「簡單易用」的數字代碼,我認爲最好使用普通的C++,但是Cython是將它公開給Python的一個很好的工具。因此,用C++編寫你的數字資料,並使用Cython來調用你的C++。這將是我可以給出的最好建議Cython是編寫C擴展到Python的優秀工具,但當C++是您真正想要的時候,它不是C++的替代品。

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

+0

有道理。我曾考慮用直接C/C++編寫代碼的主要部分,但是我認爲我應該在將來爲可能的項目學習cython。我使用的代碼的實際工作部分是 daveydave400