下列:
for x in range(rows):
for y in range(cols):
if Z[x][y] == 1:
if (N[x][y] < 2) or (N[x][y] > 3):
Z[x][y] = 0
else:
if (N[x][y] == 3):
Z[x][y] = 1
可以替换为:
set_zero_idxs = (Z==1) & ((N<2) | (N>3))
set_one_idxs = (Z!=1) & (N==3)
Z[set_zero_idxs] = 0
Z[set_one_idxs] = 1
这将比您拥有的循环需要更多的操作,但我希望它会更快。
EDIT:
所以我刚刚对这两个解决方案进行了基准测试,毫不奇怪,numpy 版本快了 180 倍:
In [49]: %timeit no_loop(z,n)
1000 loops, best of 3: 177 us per loop
In [50]: %timeit loop(z,n)
10 loops, best of 3: 31.2 ms per loop
EDIT2:
我认为这个循环:
for x in range(rows):
for y in range(cols):
Q = [q for q in [x-1, x, x+1] if ((q >= 0) and (q < cols))]
R = [r for r in [y-1, y, y+1] if ((r >= 0) and (r < rows))]
S = [Z[q][r] for q in Q for r in R if (q, r) != (x, y)]
N[x][y] = sum(S)
可以替换为:
N = np.roll(Z,1,axis=1) + np.roll(Z,-1,axis=1) + np.roll(Z,1,axis=0) + np.roll(Z,-1,axis=0)
这里有一个隐含的假设,即数组没有界限,并且x[-1]
旁边是x[0]
。如果这是一个问题,您可以在数组周围添加一个零缓冲区:
shape = Z.shape
new_shape = (shape[0]+2,shape[1]+2)
b_z = np.zeros(new_shape)
b_z[1:-1,1:-1] = Z
b_n = np.roll(b_z,1,axis=1) + np.roll(b_z,-1,axis=1) + np.roll(b_z,1,axis=0) + np.roll(b_z,-1,axis=0)
N = b_n[1:-1,1:-1]
并作为基准:
In [4]: %timeit computeNeighbours(z)
10 loops, best of 3: 140 ms per loop
In [5]: %timeit noloop_computeNeighbours(z)
10000 loops, best of 3: 133 us per loop
In [6]: %timeit noloop_with_buffer_computeNeighbours(z)
10000 loops, best of 3: 170 us per loop
所以只需稍微改进一个因素1052。 Numpy 万岁!