Cython:转置内存视图 [英] Cython: Transpose a memoryview

查看:399
本文介绍了Cython:转置内存视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题的一些背景

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

I'm trying to optimise a custom neural network code. It relies heavily on loops and I decided to use cython to speed up the calculation.

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

I followed the usual online tips: Declare all local variables with appropriate cdefs and switch off boundscheck and nonecheck. This barely gave me 10% performance.

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

Well, my code relies on lots of class members. Therefore I decided to convert the entire class into a cdef class. Turns out that cython doesn't allow numpy ndarrays as types for class members. Instead one has to use memoryviews. Unfortunately the two types seem to be vastly incompatible.

我已经遇到这个问题: Cython内存视图转置:Typeerror

I already ran into this problem: Cython memoryview transpose: Typeerror

总结:可以将np.ndarray存储在内存视图。你可以转置它并将返回的数组存储在memview中。但不是如果该memview是一个类成员。

To sum it up: You can store an np.ndarray in a memoryview. You can transpose it and store the returned array in a memview. But not if that memview is a class member. Then you have to create an intermediate memview, store the result in that and assign the intermediate memview to the class member.

这里是代码(非常感谢DavidW)

Here's the code ( many thanks to 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。还有一个相应的向后传递,所有的计算向后(对于分析梯度)。

Now I've got a new problem. The code above is from the so-called "forward-pass". There is also a corresponding backward-pass, which does all the calculations backward (for analytical gradients).

这意味着对于向后传递,我必须转置memoryview并将其存储在numpy数组中:

This means that for the backward pass, I have to transpose the memoryview and store it in a numpy array:

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

d_y必须是类成员,因此必须作为内存视图。内存视图不允许移调。他们有一个.T方法,但这对我没有帮助。

d_y has to be a class member, therefore it has to be a memoryview. Memoryviews don't allow transposing. They have a .T method, but that doesn't help me.

实际问题:


  • 如何正确存储numpy数组作为cdef类的类成员?

  • 如果答案是:as a memoryview ,如何转置内存视图?

推荐答案

我认为最好的答案是 numpy作为无类型的python对象

I think the best answer is "you store the numpy as an untyped python object"

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数组。

The small cost to doing it this way is that there's a bit of type-checking at the start of example_function to check that it is actually a 4D numpy array with the correct dtype. Provided you do a decent amount of work in the function that shouldn't matter.

另一种选择(如果你决定你真的想将它们存储为内存视图),您可以使用 np.asarray 将其转换回numpy数组而不进行复制(即它们共享数据)。

As an alternative (if you decide you really want to store them as memoryviews) you could use np.asarray to convert it back to a numpy array without making a copy (i.e. they share data).

例如

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

这篇关于Cython:转置内存视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆