我目前正在编写一种方法来构建尺寸为12 x 10的特定类型的矩阵。
给定一组重心坐标B = np.array([b1, b2, b3])
,它进行相关计算并使用切片组装矩阵。然而,虽然这些矩阵非常小,但是这种矩阵的构造最终会使我的表现陷入瓶颈,因为我需要构建几十万个。
import numpy as np
def r1(B):
"""
:param B: barycentric coordinates np.array([b1, b2, b3]) of point of evaluation
:return: (12x10) linear evaluation matrix.
"""
R = np.zeros((12, 10))
b = np.zeros((3, 3)) # beta
g = np.zeros(3) # gamma
for i in range(3):
g[i] = 2 * B[i] - 1
for j in range(3):
b[i, j] = B[i] - B[j]
R[[0, 1], 0] = g[0]
R[[2, 3], 1] = g[1]
R[[4, 5], 2] = g[2]
R[[1, 2, 7, 8], 3] = [2 * b[1, 2], 2 * b[0, 2], 2 * b[1, 2], 2 * b[0, 2]]
R[[3, 4, 9, 10], 4] = [2 * b[2, 0], 2 * b[1, 0], 2 * b[2, 0], 2 * b[1, 0]]
R[[0, 5, 6, 11], 5] = [2 * b[2, 1], 2 * b[0, 1], 2 * b[2, 1], 2 * b[0, 1]]
R[[0, 1, 6, 7], 6] = [4 * B[1], 4 * B[2], 4 * b[0, 2], 4 * b[0, 1]]
R[[2, 3, 8, 9], 7] = [4 * B[2], 4 * B[0], 4 * b[1, 0], 4 * b[1, 2]]
R[[4, 5, 10, 11], 8] = [4 * B[0], 4 * B[1], 4 * b[2, 1], 4 * b[2, 0]]
R[6:, 9] = -3 * np.array([g[0], g[0], g[1], g[1], g[2], g[2]])
return R
有没有办法加速这个?我不熟悉numpy广播,但我听过这个流行语。
b = np.array([0.1, 0.5, 0.4])
r1(b)
r1
:ncalls tottime percall cumtime percall filename:lineno(function)
125751 6.784 0.000 7.244 0.000 helper_functions.py:262(r1)
377253 0.267 0.000 0.267 0.000 {built-in method numpy.core.multiarray.zeros}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
125751 0.193 0.000 0.193 0.000 {built-in method numpy.core.multiarray.array}
我不确定如何解释此cProfile信息。数组分配需要时间吗?
感谢您的帮助!
答案 0 :(得分:0)
几乎没有快速优化:
b = B[:, None] - B[None, :] # broadcasting
g = 2 * B - 1 # Linear operation
R[0:2, 0] = g[0] # Slices vs fancy indexing
R[2:4, 1] = g[1]
R[4:6, 2] = g[2]
记下从34 µs
到27 µs
的时间。不是一个巨大的加速,但它是一个开始,更像是numpy。其余的代码似乎很好(没有深入了解矩阵应该是什么),并且需要更多的时间来进一步优化它。
如果速度对于这个矩阵非常重要,并且27 µs
确实是你的瓶颈,你可以从Cython中更快地初始化这个矩阵。