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 数组的方法:
np.asarray(memview)
- 这应该在没有复制的情况下完成(前提是您没有使用深奥的间接内存布局)。可能值得添加一个断言来检查是否没有复制。
memview.base
- 稍微小心一点。如果内存视图是切片的结果,那么 .base
将是原始的未切片对象。
保留一个并行的numpy数组和memoryview变量:
Anp = np.array(...)
cdef double[:] Amview = Anp
因为 memoryview 是一些内存的 view,对数组的修改将反映在 memoryview 中,反之亦然。 (重新分配数组变量,例如 Anp = something_else
,不会反映出来)。
总而言之,内存视图是为一项主要工作而设计的:能够快速访问各个元素。如果这不是您正在做的,那么您可能不想使用内存视图。
我在 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 数组的方法:
np.asarray(memview)
- 这应该在没有复制的情况下完成(前提是您没有使用深奥的间接内存布局)。可能值得添加一个断言来检查是否没有复制。memview.base
- 稍微小心一点。如果内存视图是切片的结果,那么.base
将是原始的未切片对象。保留一个并行的numpy数组和memoryview变量:
Anp = np.array(...) cdef double[:] Amview = Anp
因为 memoryview 是一些内存的 view,对数组的修改将反映在 memoryview 中,反之亦然。 (重新分配数组变量,例如
Anp = something_else
,不会反映出来)。
总而言之,内存视图是为一项主要工作而设计的:能够快速访问各个元素。如果这不是您正在做的,那么您可能不想使用内存视图。