我试图将linalg反函数(la.inv)的输出分配给cython中的视图 . 不幸的是,这不起作用 . 我总是可以将la.inv()的输出分配给临时的ndarray对象,然后将其内容复制到视图中 .
有没有更好的方法来做到这一点 .
cpdef int testfunc1(np.ndarray[np.float_t, ndim=2] A,
double [:,:] B) except -1:
print("inverse of A:", la.inv(A))
if np.isnan(A).any():
return -1
else:
B = la.inv(A)
return 1
cpdef int testfunc2(np.ndarray[np.float_t, ndim=2] A) except -1:
cdef long p = np.shape(A)[0], status
cdef B = np.zeros(shape=(p, p), dtype=float)
cdef double[:,:] BView = B
print("before inverse. B: ", B)
status = testfunc1(A, BView)
print("after inverse. B: ", B)
if status == -1:
return -1
else:
return 1
输出:
A = np.random.ranf(4).reshape(2, 2)
status = testfunc2(A)
if status == -1:
raise ValueError("nan cell.")
else:
print("pass")
('before inverse. B: ', array([[ 0., 0.],
[ 0., 0.]]))
('inverse of A:', array([[ 4.4407987 , -0.10307341],
[-2.26088593, 1.19604499]]))
('after inverse. B: ', array([[ 0., 0.],
[ 0., 0.]]))
3 回答
这不是由视图或Cython引起的 .
B = la.inv(A)
创建一个新数组,并在testfunc1
范围内为其命名B
. 这不会影响testfunc2
中名称为B
的数组 .请注意,您的代码(通过NumPy函数完成繁重的工作)不太可能从Cython中受益 .
使这项工作的一种方法是:
在
testfunc1
. @SaulloCastro提到这在Cython中不起作用,因为B
具有内存视图类型,但是你可以通过将参数B
声明为ndarray(不确定这一点)来使其工作 . 否则没有Cython:您可以创建一个临时缓冲区,它将接收
la.inv()
的值,然后填充内存视图:正如@MrE所指出的,如果使用
np.ndarray
而不是MemoryView,则可以使用np.copyto()
:如果我在
la.inv(A)
上创建一个mememoryview,我可以对memoryview副本执行一步,并且可能是高效的memoryview:生产环境 :
我猜测内存视图副本会更快,但样本数组太小而无法进行有意义的时间测试 .
我在https://stackoverflow.com/a/30418448/901925作为回复的一部分进行了测试
在
Python
中,您可以重新分配数组的data
缓冲区(尽管存在一定风险):cython
使用此语句在编译阶段引发有关不安全指针的错误 .灵感来自于https://stackoverflow.com/a/28855962/901925使用
np.PyArray_SimpleNewFromData
找到的示例,我尝试使用其他PyArray...
函数来执行相同类型的base
重新分配:目前我正在尝试解决
AttributeError: 'module' object has no attribute 'PyArray_SetBaseObject'
错误 .