[英]Cython: Invalid use of fused types, type cannot be specialized
我有以下MCVE:
import numpy as np
cimport numpy as np
cimport cython
from cython cimport floating
def func1(floating[:] X_data, floating alpha):
if floating is double:
dtype = np.float64
else:
dtype = np.float32
cdef floating[:] prios = np.empty(12, dtype=dtype)
cdef int ws_size = 10
C = np.argpartition(np.asarray(prios), ws_size)[:ws_size].astype(np.int32)
cdef int res = func2(X_data, alpha, C)
cpdef int func2(floating[:] X_data, floating alpha, int[:] C):
cdef int epoch = 1
return epoch
試圖運行cython test_fused.pyx
給了我:
Error compiling Cython file:
------------------------------------------------------------
...
cdef floating[:] prios = np.empty(12, dtype=dtype)
cdef int ws_size = 10
C = np.argpartition(np.asarray(prios), ws_size)[:ws_size].astype(np.int32)
cdef int res = func2(X_data, alpha, C)
^
------------------------------------------------------------
test_fused.pyx:21:24: no suitable method found
Error compiling Cython file:
------------------------------------------------------------
...
cdef floating[:] prios = np.empty(12, dtype=dtype)
cdef int ws_size = 10
C = np.argpartition(np.asarray(prios), ws_size)[:ws_size].astype(np.int32)
cdef int res = func2(X_data, alpha, C)
^
------------------------------------------------------------
test_fused.pyx:21:24: no suitable method found
Error compiling Cython file:
------------------------------------------------------------
...
cdef floating[:] prios = np.empty(12, dtype=dtype)
cdef int ws_size = 10
C = np.argpartition(np.asarray(prios), ws_size)[:ws_size].astype(np.int32)
cdef int res = func2(X_data, alpha, C)
^
------------------------------------------------------------
test_fused.pyx:21:19: Invalid use of fused types, type cannot be specialized
Error compiling Cython file:
------------------------------------------------------------
...
cdef floating[:] prios = np.empty(12, dtype=dtype)
cdef int ws_size = 10
C = np.argpartition(np.asarray(prios), ws_size)[:ws_size].astype(np.int32)
cdef int res = func2(X_data, alpha, C)
^
------------------------------------------------------------
test_fused.pyx:21:19: Invalid use of fused types, type cannot be specialized
我有一個更復雜的代碼,它也將數組C
作為運行時定義的值傳遞,這不會導致任何問題。 這個編譯錯誤的原因是什么?
我很困惑,因為稍微修改(向func1
添加一個偽關鍵字arg和向func2
添加兩個關鍵字args)使代碼編譯:
def func1(floating[:] X_data, floating alpha,
int dummy_variable=1): # added dummy_variable here
# same as before here
cdef int res = func2(X_data, alpha, C,
dummy_variable=dummy_variable)
cpdef int func2(floating[:] X_data, floating alpha, int[:] C,
int K=6, int dummy_variable=1): # added K and dummy variable here
cdef int epoch = 1
return epoch
讓我們從一個較小的重現者開始:
%%cython
import numpy as np
from cython cimport floating
def func1(floating[:] X_data):
C = np.empty(12, dtype=np.int_32)
func2(X_data, C)
cpdef func2(floating[:] X_data, int[:] C):
pass
它不編譯。
一個重要的觀察結果: func2
是一個cpdef
,這意味着Cython會將其稱為func1
的原始C函數。 這兩個C簽名將由Cython生成,用於融合的func2
函數(一個用於double
,一個用於float
):
static PyObject *__pyx_fuse_0__pyx_f_4test_func2(__Pyx_memviewslice, __Pyx_memviewslice, int __pyx_skip_dispatch); /*proto*/
static PyObject *__pyx_fuse_1__pyx_f_4test_func2(__Pyx_memviewslice, __Pyx_memviewslice, int __pyx_skip_dispatch); /*proto*/
所以C
應該是一個__Pyx_memviewslice
,但只要Cython關注它就是func1
的PyObject
,所以這個函數無法被稱為cdef
。 我不明白:為什么Cython不回歸python- def
版本?
C簽名有點誤導,Cython在編譯期間進行了更多類型檢查,因此將C
定義為
cdef float[:] C
因為即使C
在這種情況下也是__Pyx_memviewslice
它沒有正確的類型,只有
cdef int[:] C
會工作。
如果func2
被定義為
cpdef func2(floating[:] X_data, C):
相應的兩個C簽名將是
static PyObject *__pyx_fuse_0__pyx_f_4test_func2(__Pyx_memviewslice, PyObject *, int __pyx_skip_dispatch); /*proto*/
static PyObject *__pyx_fuse_1__pyx_f_4test_func2(__Pyx_memviewslice, PyObject *, int __pyx_skip_dispatch); /*proto*/
所以可以將C
這是一個PyObject
傳遞給這些函數。
因此有兩種方法可以解決編譯問題:
func1
使用cdef int[:] C
,或 int[:] C
在func2
的簽名中 那么為什么要添加一個虛擬參數,即
%%cython -a
import numpy as np
from cython cimport floating
def func1(floating[:] X_data, int dummy_variable=1):
C = np.empty(12, dtype=np.int_32)
func2(X_data, C, dummy_variable=dummy_variable)
cpdef func2(floating[:] X_data, int[:] C, int k=6, dummy_variable = 1):
pass
作品?
其實,有使代碼編譯第三種方式:通過使func2
蟒蛇只def
-功能。 在這種情況下, C
的類型在編譯期間不起作用,並且將在運行時檢查。
問題是:使用虛擬變量的情況,Cython決定將func2
調用為Python函數而不是C函數,因此類型不匹配不起作用。
您可以通過檢查帶注釋的html文件輕松查看。
但是,我不能說,Cython回歸到Python函數調用的原因是什么。 我只能說:不為k
提供價值起着重要作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.