python - Cython:转置内存 View

标签 python c++ numpy cython conv-neural-network

问题的一些背景:

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

我遵循了通常的在线提示:使用适当的 cdef 声明所有局部变量并关闭 boundscheck 和 nonecheck。这几乎没有给我 10% 的性能。

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

我已经遇到过这个问题:Cython memoryview transpose: Typeerror

总结一下:您可以将 np.ndarray 存储在内存 View 中。您可以转置它并将返回的数组存储在内存 View 中。但如果那个 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).

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

这意味着对于反向传递,我必须转置内存 View 并将其存储在一个 numpy 数组中:

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

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

实际问题:

  • 如何将 numpy 数组正确存储为 cdef 类的类成员?
  • 如果答案是:“作为内存 View ”,我该如何转置内存 View ?

最佳答案

我认为最好的答案是“你将 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 数组。只要您在该功能上做了相当多的工作,那应该无关紧要。


作为替代方案(如果您决定将它们存储为内存 View ),您可以 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/

相关文章:

python - 如何创建在Python CDK中引用自身的API网关资源策略?

python - 在设置项目时充当 defaultdict 但在获取项目时不充当 defaultdict 的嵌套字典

c++ - 如何在C++中哈希很长?

c++ - 使本地 c 库函数可全局访问

python - 计算中的不一致 - Python 和 numpy

Python numpy.corrcoef() RuntimeWarning : invalid value encountered in true_divide c/= stddev[:, 无]

python - 如何在 numpy 数组中查找值簇

python - 具有长嵌套条件的 pandas 查找

python - 将 Spyder 升级到 4.0.1 时出错 : ModuleNotFoundError: No module named 'IPython.core.inputtransformer2'

c++ - 解密字符串末尾需要 NULL 终止符是什么?