Cython Memoryview 中的数组广播

Array-Broadcasting in Cython Memoryview

我在 cython 中创建了一个类型化的内存视图,并想将它乘以一个标量:

import numpy as np
import math
cimport numpy as np

def foo():
    N = 10
    cdef np.double_t [:, :] A = np.ones(shape=(N,N),dtype=np.double_)
    cdef int i,j
    cdef double pi = math.pi
    for i in range(N):
        for j in range(N):
            A[i,j] *= pi
    return A

def bar():
    N = 10
    cdef np.double_t [:, :] A = np.ones(shape=(N,N),dtype=np.double_)
    cdef double pi = math.pi
    A *= pi
    return A

函数 foo() 执行此任务但不是很 convenient/readable。

函数 bar() 中的行 A *= pi 然而无法编译:Invalid operand types for '*' (double_t[:, :]; double).

有没有办法在 cython 内存视图上执行这样的广播操作?

不,内存视图不会这样做。内存视图实际上只是一种快速访问数组中单个元素的方法。它没有可以在数组上执行的数学运算的真正概念。

就您的 bar 函数而言,任何键入它的尝试实际上可能会使它变得更糟(即它会花费额外的时间检查类型,但最终工作是在普通情况下完成的调用 Numpy 函数)。

有多种(不是 100% 满意)从内存视图获取 Numpy 数组的方法:

  1. np.asarray(memview) - 这应该在没有复制的情况下完成(前提是您没有使用深奥的间接内存布局)。可能值得添加一个断言来检查是否没有复制。

  2. memview.base - 稍微小心一点。如果内存视图是切片的结果,那么 .base 将是原始的未切片对象。

  3. 保留一个并行的numpy数组和memoryview变量:

     Anp = np.array(...)
     cdef double[:] Amview = Anp
    

    因为 memoryview 是一些内存的 view,对数组的修改将反映在 memoryview 中,反之亦然。 (重新分配数组变量,例如 Anp = something_else,不会反映出来)。


总而言之,内存视图是为一项主要工作而设计的:能够快速访问各个元素。如果这不是您正在做的,那么您可能不想使用内存视图。