【问题标题】:Altering numpy function output array in place更改 numpy 函数输出数组
【发布时间】:2011-11-23 16:38:36
【问题描述】:

我正在尝试编写一个对数组执行数学运算并返回结果的函数。一个简化的例子可能是:

def original_func(A):
    return A[1:] + A[:-1]

为了加快速度并避免为每个函数调用分配新的输出数组,我希望将输出数组作为参数,并在适当的位置进行更改:

def inplace_func(A, out):
    out[:] = A[1:] + A[:-1]

但是,当以如下方式调用这两个函数时,

A = numpy.random.rand(1000,1000)
out = numpy.empty((999,1000))

C = original_func(A)

inplace_func(A, out)

原来的函数似乎是原地函数的两倍。这怎么解释?由于不需要分配内存,就地函数不应该更快吗?

【问题讨论】:

    标签: python arrays function numpy in-place


    【解决方案1】:

    如果您想就地执行操作,请执行

    def inplace_func(A, out): np.add(A[1:], A[:-1], out)

    这不会创建任何临时对象(A[1:] + A[:-1])。

    所有 Numpy 二进制操作都有对应的功能,这里查看列表:http://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs

    【讨论】:

      【解决方案2】:

      认为答案如下:

      在这两种情况下,您都计算A[1:] + A[:-1],在这两种情况下,您实际上都创建了一个中间矩阵。

      不过,在第二种情况下,您显式将整个新分配的大数组复制到保留的内存中。复制这样一个数组所花费的时间与原始操作大致相同,因此实际上您将时间翻了一番。

      总而言之,在第一种情况下,您可以:

      compute A[1:] + A[:-1] (~10ms)
      

      在第二种情况下,你这样做

      compute A[1:] + A[:-1] (~10ms)
      copy the result into out (~10ms)
      

      【讨论】:

      • 至于解决方案:我认为您必须自己执行循环以避免 Olivier 的回答中描述的中间数组。或者像code.google.com/p/numexpr 这样的东西可以帮助你吗?这个question 看起来也很相关。
      • 我认为您可以通过这样做来避免中间数组:out[:]=A[1:]; out+=A[:-1] 当然,您的实际算法可能更难简化。当然要不惜一切代价避免循环。您通常可以使用累积和 ufunc 来做一些有创意的事情。
      【解决方案3】:

      我同意 Olivers 的解释。如果要就地执行操作,则必须手动循环遍历数组。这会慢得多,但如果您需要速度,您可以使用 Cython,它为您提供纯 C 实现的速度。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-04
        • 1970-01-01
        相关资源
        最近更新 更多