Python 使用视图加快数组迭代

Python 使用视图加快数组迭代,python,arrays,performance,numpy,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:] 但这仍然会产生拷贝,我想知道是否有办

如果我有一个大的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:]

但这仍然会产生拷贝,我想知道是否有办法变得更快。

有时候你只需要临时的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数组方法可能会变得更慢。

有时您只需要临时数组,而无法重写

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
阵列方法可能会变得更慢。

你可以在一次扫描中完成,在适当的位置你可以在一次扫描中完成,在适当的位置