Some background for the question:
我正在尝试优化自定义神经网络代码 . 它在很大程度上依赖于循环,我决定使用cython来加速计算 .
我遵循通常的在线提示:使用适当的cdef声明所有局部变量,并关闭boundscheck和nonecheck . 这几乎没有给我10%的表现 .
好吧,我的代码依赖于很多类成员 . 因此我决定将整个类转换为cdef类 . 事实证明,cython不允许将numpy ndarrays作为类成员的类型 . 相反,必须使用内存视图 . 不幸的是,这两种类型似乎非常不相容 .
我已经遇到过这个问题:Cython memoryview transpose: Typeerror
总结一下:您可以将np.ndarray存储在memoryview中 . 您可以转置它并将返回的数组存储在memview中 . 但是,如果该memview是一个类成员 . 然后,您必须创建一个中间memview,将结果存储在其中,并将中间memview分配给类成员 .
这是代码(非常感谢DavidW)
def double[:,:,:,:] temporary_view_of_transpose
# temporary_view_of_transpose now "looks at" the memory allocated by transpose
# no square brackets!
temporary_view_of_transpose = out_image.transpose(1, 0, 2, 3)
# data is copied from temporary_view_of_transpose to self.y
self.y[...] = temporary_view_of_transpose # (remembering that self.y must be the correct shape before this assignment).
现在我遇到了一个新问题 . 上面的代码来自所谓的“前向传递” . 还有一个相应的向后传递,它向后进行所有计算(对于分析梯度) .
这意味着对于向后传递,我必须转置内存视图并将其存储在一个numpy数组中:
cdef np.ndarray[DTYPE_t, ndim=4] d_out_image = self.d_y.transpose(1, 0, 2,3)
d_y必须是类成员,因此它必须是一个内存视图 . Memoryviews不允许转置 . 他们有一个.T方法,但这对我没有帮助 .
Actual Question:
-
如何正确存储numpy数组作为cdef类的类成员?
-
如果答案是:"as a memoryview",如何转置内存视图?
1 回答
我认为最好的答案是“你将numpy存储为无类型的python对象”
这样做的小成本是在
example_function
的开头有一些类型检查来检查它实际上是一个具有正确dtype的4D numpy数组 . 如果你在函数中做了相当多的工作,那应该不重要 .作为替代方案(如果您确定要将它们存储为内存视图),您可以use np.asarray to convert it back to a numpy array without making a copy(即它们共享数据) .
例如