使用视图更快地进行数组迭代

时间:2013-05-23 13:38:51

标签: python arrays performance numpy

如果我有一个大的numpy数组x我可以加速许多迭代操作,而不是写

x[1:-1] = 5*x[1:-1]

我可以用

x[1:-1] *= 5

速度更快,因为与第一个示例相比,它避免了使用值5*x[1:-1]不必要地创建其他数组。

我的问题出现了:是否有可能加快像

这样的更一般的迭代
x[1:-1] = 5*x[1:-1] + x[:-2]

以类似的方式?到目前为止,我只想出了

x[1:-1] = x[:-2]
x[1:-1] += 5*x[2:]

但这仍然会创建副本,我想知道是否有办法变得更快。

1 个答案:

答案 0 :(得分:1)

有时你只需要临时的arryas,你就不能重写

x[1:-1] += 5*x[2:]

作为视图上的操作。

当您需要临时数组时,模拟到就地计算是创建一些临时数组,并在计算的每个阶段使用它们作为输出。你仍然有更多的指针数学,但你不必多次在内存中创建空间。然后你可以将上面的行重写为:

np.multiply(x[2:], 5, out=temp)
x[1:-1] += temp

在这里,我假设temp的大小为x[-1:1],这是我通常为处理边界的常见问题所做的。

通过就地计算,您无法多次运行具有timeit的精确等式,因为数字会以指数方式增长,但这是5x替换为1x的测试:

import numpy as np
from timeit import timeit

N = 100000000
x = np.arange(N, dtype=np.int)
temp = np.zeros((N-2,), dtype=np.int)

def f0(x, temp):
    x[1:-1] += 1*x[2:]

def f1(x, temp):
    np.multiply(x[1:-1], 1, out=temp)
    x[1:-1] += temp

print timeit("f0(x, temp)", "from __main__ import f0, f1, x, temp", number=100)
print timeit("f1(x, temp)", "from __main__ import f0, f1, x, temp", number=100)

给出:

71.543628931
44.719383955

# or, for N /= 100, and number *= 10
5.37844896317
4.50015997887

对于小得多的数组,out数组方法可能会变慢。