【问题标题】:Performance of returning a new array and modifying a passed-in array返回新数组和修改传入数组的性能
【发布时间】:2015-01-01 00:36:54
【问题描述】:

[Related]

在下面的快照中,我比较了速度

  • 通过切片分配修改现有数组
  • 只是返回一个新的、修改后的数组

似乎后者更快。为什么会这样?


编辑:更新了建议,以及使用 numpy 的矢量化 add() 的版本,现在是最快的。

【问题讨论】:

    标签: python python-2.7 numpy


    【解决方案1】:

    我对 python/numpy 的内部结构了解不多,但这是我假设正在发生的事情。只看代码,我就觉得finlinefreturn 做了更多的工作,因为finline 拥有freturn 所做的所有语句(x + 1.0)等等。

    也许这可以解释发生了什么:

    >>> x = np.random.rand(N)
    >>> y = np.zeros(N)
    >>> super(np.ndarray, y).__repr__()
    Out[33]: '<numpy.ndarray object at 0x24c9c80>'
    >>> finline(x, y)
    >>> y     # see that y was modified
    Out[35]: 
    array([ 1.92772158,  1.47729293,  1.96549695, ...,  1.37821499,
            1.8672971 ,  1.17013856])
    >>> super(np.ndarray, y).__repr__()
    Out[36]: '<numpy.ndarray object at 0x24c9c80>'  # address of y did not change
    >>> y = freturn(x)
    >>> super(np.ndarray, y).__repr__()
    Out[38]: '<numpy.ndarray object at 0x24c9fc0>'  # address of y changed
    

    所以本质上,我认为finline 正在做更多的工作,因为它必须遍历 y 的元素并将它们中的每一个初始化为x + 1.0 操作返回的数组。另一方面,y = freturn(x) 可能只是将y 指针的值重新初始化为等于x + 1.0 操作初始化的数组的地址。

    【讨论】:

    • 好的,我想你是说内联版本正在做一个额外的复制,即计算的 RHS 产生一个中间体,作为一个单独的步骤分配给 inline-y 的内存?可能。我现在正在查看dis.dis() 的输出...
    • @cjrh,是的,在这种情况下会有一个中间人。为了避免中间,你可以这样做:y[:] = x, y += 1.0。它更快吗?
    • @cjrh:没错。我认为这有点像 C++ 中复制和移动构造函数之间的区别。
    • @RomanL:我为您的建议添加了一个版本。它似乎比其他人慢。我还加了一个np.add()的版本,现在最快了。
    • @cjrh:我看不出它会变慢的原因,而且它在我的机器上更快。当然,np.add 是要走的路。
    【解决方案2】:
    • x + 1 将创建一个新数组。
    • y[:] = x + 1:新建数组,将所有数据复制到y
    • y = x + 1:创建一个新数组并将名称y 绑定到这个新数组。
    • np.add(x, 1, out=y):不要新建数组,这样最快。

    代码如下:

    x = np.zeros(1000000)
    y = np.zeros_like(x)
    %timeit x + 1
    %timeit y[:] = x + 1
    %timeit np.add(x, 1, out=y)
    

    输出:

    100 loops, best of 3: 4.2 ms per loop
    100 loops, best of 3: 6.83 ms per loop
    100 loops, best of 3: 2.5 ms per loop
    

    【讨论】:

    • 谢谢!我最终自己到达了那里,但无论如何都有一些要点:)
    猜你喜欢
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    • 2021-11-17
    相关资源
    最近更新 更多