(w/r/t OP 的最后一句话:我不知道这种 numpy/scipy 方法,但是 w/r/t OP 标题中的问题(即改进NumPy 点性能)下面的内容应该会有所帮助。换句话说,我的回答是针对提高大多数步骤的性能,这些步骤包括你的 Y) 函数。
首先,这应该会给您带来比普通 NumPy dot 方法明显的提升:
>>> from scipy.linalg import blas as FB
>>> vx = FB.dgemm(alpha=1., a=v1, b=v2, trans_b=True)
请注意,v1、v2 这两个数组在 C_FORTRAN 顺序中都
您可以通过数组的 flags 属性访问 NumPy 数组的字节顺序,如下所示:
>>> c = NP.ones((4, 3))
>>> c.flags
C_CONTIGUOUS : True # refers to C-contiguous order
F_CONTIGUOUS : False # fortran-contiguous
OWNDATA : True
MASKNA : False
OWNMASKNA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
要更改其中一个数组的顺序,使两者对齐,只需调用 NumPy 数组构造函数,传入数组并将适当的 order 标志设置为 True
>>> c = NP.array(c, order="F")
>>> c.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : True
MASKNA : False
OWNMASKNA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
您可以通过利用数组顺序对齐来进一步优化减少因复制原始数组而导致的过多内存消耗。
但是为什么数组在传递给dot之前要被复制呢?
点积依赖于 BLAS 运算。这些操作需要以 C 连续顺序存储的数组——正是这种约束导致数组被复制。
另一方面,转置确实不影响副本,但不幸的是以Fortran顺序返回结果:
因此,要消除性能瓶颈,您需要消除谓词数组复制步骤;要做到这一点,只需将两个数组都以 C 连续顺序传递给 dot*。
所以要计算 dot(A.T., A) 而不制作额外的副本:
>>> import scipy.linalg.blas as FB
>>> vx = FB.dgemm(alpha=1.0, a=A.T, b=A.T, trans_b=True)
总之,上面的表达式(连同谓词导入语句)可以代替点,提供相同的功能但性能更好
你可以像这样将该表达式绑定到一个函数:
>>> super_dot = lambda v, w: FB.dgemm(alpha=1., a=v.T, b=w.T, trans_b=True)