从 numpy.ndarray 初始化 cython 中的 memoryview 切片

Initialize slices of memoryview in cython from numpy.ndarray

我正在尝试初始化内存视图的一部分(不是整个)。假设我将 memoryview A 作为 class(扩展类型)

的属性
from cython.view cimport array as cvarray

N = 1000
cdef double[:,:,::1] A = cvarray(shape=(2,N,N),itemsize=sizeof(double),format='d')

现在,我试图在 cdef 函数中初始化它。我像这样初始化整个内存视图没有问题

# From elsewhere we have loaded a numpy.ndarray B of size (2,N,N)
A[:,:,:] = B

当初始化器 B 是 3D 数组 (2,N,N) 时这很好,这样我们就不必 切片 A。但是现在,问题来了:假设我有大小为 (N,N) 的二维数组 B1B2,并尝试初始化为

A[0,:,:] = B1
A[1,:,:] = B2

这给了我以下错误:

TypeError: only length-1 arrays can be converted to Python scalars

当然我可以将所有数据从B1B2一个一个复制到A,但是这样效率不高。这个过程是循环的,大小N很大。 B1B2netcdf 文件形式加载为 numpy.ndarray 类型。

此外,我将 A 定义为 memoryview,这样我就可以在代码的其他地方使用 nogil 函数来访问 A.

我想知道是否有一种有效的方法可以像上面那样初始化 memoryview,或者至少,以某种方式使用 B1B2 的指针并将它们放在一个可迭代的数组中。谢谢。

我可以找到两个选项:

  1. 如果您键入 B1B2 作为内存视图,它会起作用。
  2. 您可以访问内存视图的 base 属性以获取 cvarray 和索引:

    A.base[0,:,:] = B1
    A.base[1,:,:] = B2
    

    我认为这不一定适用于所有 memoryview 兼容对象(它们需要定义缓冲区接口而不是有用的 __getitem__)但它应该适用于大多数对象,包括 cvarray.