【发布时间】:2020-03-10 18:52:36
【问题描述】:
是否有与以下功能等效的标准库/numpy:
def augmented_assignment_sum(iterable, start=0):
for n in iterable:
start += n
return start
?
虽然sum(ITERABLE) 非常优雅,但它使用+ 运算符而不是+=,这在np.ndarray 对象的情况下可能会影响性能。
我已经测试过我的函数可能和sum() 一样快(而使用+ 的等效函数要慢得多)。由于它是一个纯 Python 函数,我猜它的性能仍然有缺陷,因此我正在寻找一些替代方案:
In [49]: ARRAYS = [np.random.random((1000000)) for _ in range(100)]
In [50]: def not_augmented_assignment_sum(iterable, start=0):
...: for n in iterable:
...: start = start + n
...: return start
...:
In [51]: %timeit not_augmented_assignment_sum(ARRAYS)
63.6 ms ± 8.88 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [52]: %timeit sum(ARRAYS)
31.2 ms ± 2.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [53]: %timeit augmented_assignment_sum(ARRAYS)
31.2 ms ± 4.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [54]: %timeit not_augmented_assignment_sum(ARRAYS)
62.5 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [55]: %timeit sum(ARRAYS)
37 ms ± 9.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [56]: %timeit augmented_assignment_sum(ARRAYS)
27.7 ms ± 2.53 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
我曾尝试将functools.reduce 与operator.iadd 结合使用,但其性能相似:
In [79]: %timeit reduce(iadd, ARRAYS, 0)
33.4 ms ± 11.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [80]: %timeit reduce(iadd, ARRAYS, 0)
29.4 ms ± 2.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
我也对内存效率感兴趣,因此更喜欢增强分配,因为它们不需要创建中间对象。
【问题讨论】:
-
np.add.reduce(ARRAYS)? -
@DanielMesejo 可悲的是
374 ms ± 83.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each):-( 虽然如果ARRAYS是二维数组会快得多。 -
@DanielMesejo 它返回一个标量,除非用
axis=0调用。然后它需要355 ms ± 16.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each):-( 在内部它使用np.add.reduce()(numpy v. 1.15.4) -
np.dot(your_array, np.ones(len(your_array)))怎么样。应该转移到 BLAS 并且相当快。
标签: python performance numpy standard-library augmented-assignment