【问题标题】:Speed of copying numpy array复制numpy数组的速度
【发布时间】:2018-06-12 20:15:38
【问题描述】:

我想知道使用b = np.array(a) 而不是b = np.copy(a) 将Numpy 数组a 复制到b 中是否有任何缺点。当我%timeit 时,前者可以快 100%。

在这两种情况下b is aFalse,我可以操纵b 保持a 不变,所以我想这符合.copy() 的预期。

我错过了什么吗?使用np.array复制数组有什么不妥之处?

使用 python 3.6.5,numpy 1.14.2,而对于较大的尺寸,速度差异会迅速缩小:

a = np.arange(1000)

%timeit np.array(a)
501 ns ± 30.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.copy(a)  
1.1 µs ± 35.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

【问题讨论】:

  • 我看到速度差异消失了,实际上随着我增加数组的大小而逆转。他们与numpy.arange(10000000) 的工作差不多。
  • 嗯,你是对的 - 但即使数组中有 1E9 个元素,差异也很小。相反,有几千个,arraycopy 快得多。
  • 这种比较的一个挑战是将函数调用开销与复制数据的实际工作分开。部分开销只是创建新数组的任务。 np.ones(a.shape,int) 几乎与 np.array(a) 一样长。将copy 时间与a+0 之类的简单数学任务进行比较也可能会有所帮助。

标签: python arrays numpy


【解决方案1】:

来自numpy.copy的文档:

这相当于:

>>> np.array(a, copy=True)

另外,如果您查看source code

def copy(a, order='K'):
    return array(a, order=order, copy=True)

一些时间安排:

In [1]: import numpy as np

In [2]: a = np.ascontiguousarray(np.random.randint(0, 20000, 1000))

In [3]: %timeit b = np.array(a)
562 ns ± 10.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit b = np.array(a, order='K', copy=True)
1.1 µs ± 10.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [5]: %timeit b = np.copy(a)
1.21 µs ± 9.28 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [6]: a = np.ascontiguousarray(np.random.randint(0, 20000, 1000000))

In [7]: %timeit b = np.array(a)
310 µs ± 6.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [8]: %timeit b = np.array(a, order='K', copy=True)
311 µs ± 2.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [9]: %timeit b = np.copy(a)
313 µs ± 4.33 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [10]: print(np.__version__)
1.13.3

出乎意料的是,简单地将参数显式设置为其默认值会改变np.array() 的执行速度。另一方面,也许仅仅处理这些显式参数会增加足够的执行时间来对小数组产生影响。实际上,从source code for the numpy.array() 可以看出,当提供关键字参数时,会执行更多检查和更多处理,例如,请参阅goto full_path。如果没有设置关键字参数,执行会一直跳到goto finish。这种开销(关键字参数的额外处理)是您在小数组的计时中检测到的。对于较大的数组,与复制数组的实际时间相比,这种开销是微不足道的。

【讨论】:

  • 出色的侦探工作,谢谢! 这本书也很棒:answers.opencv.org/question/219040/…
  • 示例 3 和 7 看起来相同,但时间不同
  • 它们是相同的,除了数组大小:1e3 代表 3 和 1e6 代表 7th。
【解决方案2】:

“使用 np.array 复制数组有什么不妥之处?”

我认为它更难阅读。因为array 复制并不明显,例如类似的asarray 不需要复制就不会复制。读者基本上必须知道copy 关键字参数的默认值才能确定。

【讨论】:

    【解决方案3】:

    正如 AGN 所指出的,np.array 比 np.copy 快,因为本质上后者是前者的包装器。这意味着python“失去”了一些额外的时间来搜索这两个函数。装饰器也会发生类似的情况。

    这个额外的时间对于实际目的来说是微不足道的,并且您可以获得更好的代码可读性。

    您可以使用一个大数组来测试它(数组创建需要主要时间),您会发现两者的 %timeit 差异很小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-17
      • 1970-01-01
      • 2019-08-11
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      相关资源
      最近更新 更多