构造一个相当小的numpy数组时的瓶颈。索引问题?

时间:2018-02-09 11:15:10

标签: python arrays performance numpy matrix

我目前正在编写一种方法来构建尺寸为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)

cProfile结果为125751次调用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信息。数组分配需要时间吗?

感谢您的帮助!

1 个答案:

答案 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 µs27 µs的时间。不是一个巨大的加速,但它是一个开始,更像是numpy。其余的代码似乎很好(没有深入了解矩阵应该是什么),并且需要更多的时间来进一步优化它。

如果速度对于这个矩阵非常重要,并且27 µs确实是你的瓶颈,你可以从Cython中更快地初始化这个矩阵。