哪种方法更快,为什么是 np.sum(arr) 与 arr.sum()?



哪个是更快的方法?就像它们都不一样吗?

start = time.time()
arr = np.array([1,2,3,4,5,6,7,8,9,0,12])
total_price =  np.sum(arr[arr < 7])* 2.14
print(total_price)
print('Duration: {} seconds'.format(time.time() - start))
start = time.time()
arr = np.array([1,2,3,4,5,6,7,8,9,0,12])
total_price =  (arr[arr<7]).sum()* 2.14
print(total_price)
print('Duration: {} seconds'.format(time.time() - start))

在一次又一次地运行代码时,它们都给出了不同的结果执行时间。有时前一种方法更快,有时更晚。

删除巨大的文档字符串,np.sum的代码是

@array_function_dispatch(_sum_dispatcher)
def sum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue,
initial=np._NoValue, where=np._NoValue):
if isinstance(a, _gentype):
# 2018-02-25, 1.15.0
warnings.warn(
"Calling np.sum(generator) is deprecated, and in the future will give a different result. "
"Use np.sum(np.fromiter(generator)) or the python sum builtin instead.",
DeprecationWarning, stacklevel=3)
res = _sum_(a)
if out is not None:
out[...] = res
return out
return res
return _wrapreduction(a, np.add, 'sum', axis, dtype, out, keepdims=keepdims,
initial=initial, where=where)

array_function_dispatch处理非 NumPy 类型可能提供的__array_function__重写,而_wrapreduction负责确保np._NoValue不会传递到基础实现,以及决定是调用sum方法(对于非数组输入(还是add.reduce(对于数组输入(。

因此,它会执行一系列检查来处理非数组输入,然后最终将任务传递给np.add.reduce输入是否为数组。

同时,np.ndarray.sum是这样的:

static PyObject *
array_sum(PyArrayObject *self, PyObject *args, PyObject *kwds)
{
NPY_FORWARD_NDARRAY_METHOD("_sum");
}

其中NPY_FORWARD_NDARRAY_METHOD是将操作转发到numpy.core._methods._sum的宏:

def _sum(a, axis=None, dtype=None, out=None, keepdims=False,
initial=_NoValue, where=True):
return umr_sum(a, axis, dtype, out, keepdims, initial, where)

umr_sumnp.add.reduce的别名。

两个代码路径最终都以np.add.reduce结束,但ndarray.sum代码路径并不涉及非数组输入的所有预检查工作,因为数组已经知道它是一个数组。

在这些测试中,计算时间本身足够小,以至于大量的预检查会产生很大的不同:

In [607]: timeit np.sum(np.arange(1000))                                                 
15.4 µs ± 42.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [608]: timeit np.arange(1000).sum()                                                   
12.2 µs ± 29.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [609]: timeit np.add.reduce(np.arange(1000))                                          
9.19 µs ± 17.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

numpy有许多这样的函数/方法对。 使用最方便的 - 并且在您的代码中看起来最漂亮!

最新更新