问题的一些背景:

我正在尝试优化自定义神经网络代码。
它严重依赖循环,因此我决定使用cython加快计算速度。

我遵循了通常的在线技巧:使用适当的cdef声明所有局部变量,并关闭boundscheck和nonecheck。这勉强给了我10%的表现。

好吧,我的代码依赖于许多类成员。因此,我决定将整个类转换为cdef类。事实证明,cython不允许将numpy ndarrays作为类成员的类型。相反,必须使用memoryviews。
不幸的是,这两种类型似乎完全不兼容。

我已经遇到了这个问题: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).

现在,我遇到了一个新问题。
上面的代码来自所谓的“正向传递”。还有一个相应的向后遍历,它向后进行所有计算(对于分析梯度)。

这意味着对于向后传递,我必须转置memoryview并将其存储在numpy数组中:
cdef np.ndarray[DTYPE_t, ndim=4] d_out_image = self.d_y.transpose(1, 0, 2,3)

d_y必须是类成员,因此它必须是memoryview。 Memoryview不允许转置。他们有一个.T方法,但这对我没有帮助。

实际问题:
  • 如何正确地将numpy数组存储为cdef类的类成员?
  • 如果答案是:“作为memoryview”,如何转置memoryview?
  • 最佳答案

    我认为最好的答案是“您将numpy存储为无类型的python对象”

    cdef class C:
        cdef object array
    
        def example_function(self):
            # if you want to use the fast Cython array indexing in a function
            # you can do:
            cdef np.ndarray[np.float64_t,ndim=4] self_array = self.array
            # or
            cdef np.float64_t[:,:,:,:] self_array2 = self.array
    
            # note that neither of these are copies - they're references
            # to exactly the same array and so if you modify one it'll modify
            # self.array too
    
        def function2(self):
            return self.array.transpose(1,0,2,3) # works fine!
    

    这样做的代价很小,是在example_function的开头进行了一些类型检查,以检查它实际上是具有正确dtype的4D numpy数组。只要您在该功能上做了大量的工作就可以了。

    作为一种替代方案(如果您确定确实要将它们存储为memoryviews),则可以use np.asarray to convert it back to a numpy array without making a copy(即它们共享数据)。

    例如
    cdef np.ndarray[DTYPE_t, ndim=4] d_out_image = np.asarray(self.d_y).transpose(1, 0, 2,3)
    

    关于python - Cython:转置内存 View ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37226813/

    10-11 00:39