Numpy Cython Memoryview中的阵列广播

Numpy Cython Memoryview中的阵列广播,numpy,cython,array-broadcasting,typed-memory-views,Numpy,Cython,Array Broadcasting,Typed Memory Views,我用cython创建了一个类型化的memoryview,并希望将其乘以标量: 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)

我用cython创建了一个类型化的memoryview,并希望将其乘以标量:

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()
执行此任务,但不太方便/可读

但是,函数
bar()
中的行
A*=pi
未编译:
对“*”的操作数类型无效(double_t[:,:];double)


有没有办法在cython memoryview上执行这样的广播操作?

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

对于
bar
函数,任何尝试键入它的操作都可能会使情况变得更糟(即,它将花费额外的时间检查类型,但最终工作是在对Numpy函数的普通调用中完成的)

从memoryview中获取Numpy数组有多种方法(并非100%令人满意):

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

  • memview.base
    -对此要稍微小心。如果memoryview是切片的结果,则
    .base
    将是原始的未切片对象

  • 保留并行numpy数组和memoryview变量:

     Anp = np.array(...)
     cdef double[:] Amview = Anp
    
    因为memoryview是一些内存的视图,所以对数组的修改将反映在memoryview中,反之亦然。(但不会反映重新分配数组变量,例如,
    Anp=something\u other



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

    谢谢您的建议!您是对的,最好的方法可能是使用类型化的memviews进行快速索引,或者使用经典的numpy函数。