- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想将 2D numpy 数组传递给 cdef 函数,其中数组的维度可以变化。这是我尝试过的:
cimport numpy as cnp
input = numpy.array([[3.34, 2.2],[1.1, -0.6]])
input = input[:,:].astype(np.double)
cdef int nrows = 2
cdef int ncols = 2
# output of function
cdef cnp.ndarray[cnp.uint8_t, ndim=2] output = np.zeros((2,2), dtype=np.uint8)
test_array(nrows, ncols, &input[0], <unsigned char**>output.data)
我的 test_array 函数在哪里:
cdef void test_array(Py_ssize_t nrows, Py_ssize_t ncols, double **x, unsigned char **output) nogil:
output[0][0]=1
output[1][0]=0
output[1][1]=1
output[0][1]=0
我的函数原型(prototype)是:
cdef void test_array(Py_ssize_t nrows, Py_ssize_t ncols, double **x, unsigned char **output) nogil
当我编译时,我收到一条错误消息“无法获取 Python 对象的地址”并指向 &input[0]
。该语法适用于一维数组,但我不确定二维数组的语法是什么。我也试过 &input[0][0]
但这也是错误的。
最佳答案
不清楚你想达到什么目的:
答:如果它应该是一个纯cython函数那么你应该使用typed memory view ,这意味着你的函数签名应该是
cdef void test_array(double[:,:] x, unsigned char[:,:] output) nogil:
没有nrows
、ncols
,因为类型化的内存 View 有这些信息(类似于std::vector
)。
B: array_test
实际上是一个 c 函数的包装器,它需要 double **
和 unsigned char **
,那你应该看看这个SO-question .
其实,我想解释一下,为什么你的尝试没有奏效。
首先,为什么 &input[0]
不起作用?真正的问题是什么是 input[0]
:
import numpy as np
input=np.zeros((3,3))
type(input[0])
<type 'numpy.ndarray'>
type(input[:,0])
<type 'numpy.ndarray'>
type(input[0,0])
<type 'numpy.float64'>
所以 input
是一个 numpy.ndarray
,表示一个 python 对象,而 cython 拒绝获取它的地址。 input[0,0]
也是如此——它是一个 python 对象。到目前为止没有运气。
要让它工作,你需要 input
是一个 cython-numpy 数组(我不知道如何更好地表达它 - 看看这个例子):
import numpy as np
cimport numpy as np #that the way it is usually imported
def try_me():
cdef np.ndarray[double, ndim=2] input = np.array([[3.34, 2.2],[1.1, -0.6]])
cdef double *ptr1=&input[0,0]
cdef double *ptr2=&input[1,0]
print ptr1[0], ptr2[1] #prints 3.34 and -0.6
重要部分:input
不再被视为/解释为 python 对象,而是类型为 cython 类型的 np.ndarray[double, ndim=2]
和这就是使语法 &input[0,0]
成为可能的原因。
也许更精确的理解方式如下:cimport numpy
为我们提供了处理 numpy 数组的额外工具,因此我们可以访问在纯 python 中无法访问的内部结构。
但是,&input[0,0]
不是double **
类型,而是double *
类型,因为numpy .ndarray
只是一个连续的内存块,只有运算符 [i,j]
模拟了 2d 的感觉:
How it feels:
A[0] -> A00 A01 A02
A[1] -> A10 A11 A12
The real layout in the memory:
A00 A01 A02 A10 A11 A12
没有指向行的指针,但您可以通过 cdef double *ptr2=&input[row_id,0]
创建它们,如何处理它在 above mentioned question 中讨论。 .
说 numpy.ndarray
只是一段连续的内存是一种简化 - numpy.ndarray
是一个相当复杂的野兽!请考虑以下示例:
import numpy as np
cimport numpy as np
def try_me2():
cdef np.ndarray[double, ndim=2] input = np.array([[1.0, 2.0],
[3.0, 4.0]])
cdef np.ndarray[double, ndim=1] column = input[:,1]
cdef double *ptr = &column[0]
print column #prints column "2 4"
print ptr[0],ptr[1] #prints "2 3" and not "2 4"!
现在,input
和 column
共享同一内存,内存中 input[1][0]
保存在 input[0][1]=column[0]
并且只有 input[1][1]=column[1]
。 ptr[1]
获取 input[0][1]
旁边的存储单元,这是 input[1][0]=3
而不是 input[1][1]=4
。
关于python - cython:将 2D numpy 数组传递给 cdef 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46714147/
在不牺牲 cdef 调用程序中的 cdef 的情况下,他们有什么方法可以使这项工作正常进行吗? (也没有使用 cpdef) from array import * from numpy import
我正在学习 Cython,现在正在试验它。我尝试了基本的 cdef 类示例程序,它运行良好。 现在我想做的是在 cdef 类类型中混合使用 cdef 和非 cdef 属性,就像这样 cdef clas
我正在尝试在 cython 中实现通用排序算法。因此,我创建了以下模块,它在 sorter_t 类中实现了 Heapsort 算法: # file general_sort_c.pyx from li
我想要一个 cdef 类的 cython 数组: cdef class Child: cdef int i def do(self): self.i += 1 cdef
当我声明一个返回 double 的 cdef 函数时,我会写 cdef double method_name(...) 。如果它没有返回任何东西并且我只是将它省略给 cdef method_name(
我在同一个模块的所有函数中使用了很多相同类型的变量: def func1(double x): cdef double a,b,c a = x b = x**2 c =
我有一个使用许多 nogil cdef 函数的应用程序,我想对它们进行分析为了找到瓶颈。 我尝试将 profile=True 指令传递给 Cython,但这些函数似乎是免疫的,因此 cProfile.
感谢 stackoverflow 上的一些人,我终于让 cython 工作了,但现在有一个问题。从我不使用 cdef 到我使用 cdef 确实没有速度提升。不要误会我的意思,当我使用 cython 编
关于像这样应用于 cdef extern 的“nogil”,有一件事我不完全理解: cdef extern from "pthread.h" nogil: ctypedef struct pt
我想要一个 cdef 类的 cython 数组: cdef class Child: cdef int i def do(self): self.i += 1 cdef
我想知道在声明函数时def、cdef 和cpdef 之间的区别。def 和其他 def 之间的区别或多或少是清楚的。而且我还看到,有时它会在声明中添加返回类型 (cdef void/double/in
我正在尝试在运行 Alpine 的 Docker 镜像上编译一些代码。但是,gcc 由于 fatal error: sys/cdefs.h: No such file or directory 而不断
常设问题: 为什么 Cython 编译中的其他错误指向特定的错误行,而这个却没有? 更新前: 由于难以编译扩展类型,正如下面“不会编译”链接中所引用的,人们认为 AssertionError 与扩展类
是否有一种 cython-ic 方法可以将 cdef 数组设置为零。我有一个具有以下签名的函数: cdef cget_values(double[:] cpc_x, double[:] cpc_y):
我正在尝试改进此使用列表类型的代码: # CLASS ORDERC # ################ cdef class OrderC: cdef int _side cdef
我很好奇以下内容是否有效,其中只有部分变量在类型声明的类中进行了类型声明。也就是说,在这种情况下,类之前的 cdef 会无效吗? cdef class CythonClass: cdef in
我有一个 cdef 函数返回一个 (int, int) 元组。我需要传播异常,因此必须为异常指定返回类型。由于我的函数从不返回负值,这可能例如是 (-1, -1)。使用 documentation 中
class Myuser * MyClient_GetMyUser(AUser aUser); 这是尝试使用 ffi.cdef 声明该函数的错误: Error: dllImport.lua:861:
尝试使用 XCode 在 Mac Lion (10.7) 上编译我的 C++ 应用程序时,我一直遇到错误。编译器提示 cdefs.h 中的一行(包含在 syslog.h 中)带有错误 expected
我已经使用 cdef 定义了一个 python 类,它用 Cython 包装了一个 C++ 类并且它工作正常。但是,当我在 python 或类中使用 help(class) 时?在 ipython 中
我是一名优秀的程序员,十分优秀!