1、问题背景
- 给定一个(x,y)处的节点网格,每个节点有一个值(0…255)从0开始。
- 有N个输入坐标,每个坐标在(0…x, 0…y)的范围内。
- 一个值Z,它定义了节点的“邻域”。
- 增加输入坐标及其邻居节点的值。网格边缘之外的邻居被忽略。
- 基准案例:1024x1024个节点的网格,400个输入坐标,Z的范围是75个节点。
- 处理应该是O(xyZ*N)。期望x、y和Z保持在大致与基准案例中的值相同,但输入坐标的数量N可能会增加到100,000。目标是最大程度地减少处理时间。
2、解决方案
- 使用list comprehension代替内部for循环。
- 使用map()函数代替外部for循环。
- 使用静态变量来避免多次查找非局部作用域变量。
- 建立一个单独的map()操作来将值限制为255。
- 使用更快的算法来执行计算。例如,使用C扩展。
以下是用Python编写的示例代码来处理网格中的数据:
import time
import numpy as np
import random
def f2(x, y, n, z):
rows = [[0] * x for i in range(y)]
for i in range(n):
inputX, inputY = (int(x * random.random()), int(y * random.random()))
topleft = (inputX - z, inputY - z)
for i in range(max(0, topleft[0]), min(topleft[0] + (z * 2), x)):
l = max(0, topleft[1])
r = min(topleft[1] + (z * 2), y)
rows[i][l:r] = [j + (j < 255) for j in rows[i][l:r]]
def f3(x, y, n, z):
inputs = [(int(x * random.random()), int(y * random.random())) for i in range(n)]
rows = map(g, inputs)
def g(input):
inputX, inputY = input
topleft = (inputX - 75, inputY - 75)
for i in range(max(0, topleft[0]), min(topleft[0] + (75 * 2), 1024)):
l = max(0, topleft[1])
r = min(topleft[1] + (75 * 2), 1024)
rows[i][l:r] = [j + (j < 255) for j in rows[i][l:r]]
def f4(x, y, n, z):
rows = [[0] * y for i in range(x)]
rr = random.randrange
inc = (1).__add__
sat = (0xff).__and__
for i in range(n):
inputX, inputY = rr(x), rr(y)
b = max(0, inputX - z)
t = min(inputX + z, x)
l = max(0, inputY - z)
r = min(inputY + z, y)
for i in range(b, t):
rows[i][l:r] = map(inc, rows[i][l:r])
for i in range(x):
rows[i] = map(sat, rows[i])
def f5(x, y, n, z):
# 使用 NumPy 数组
rows = np.zeros((x, y), dtype=np.uint8)
for i in range(n):
inputX, inputY = (int(x * random.random()), int(y * random.random()))
topleft = (inputX - z, inputY - z)
rows[max(0, topleft[0]):min(topleft[0] + (z * 2), x),
max(0, topleft[1]):min(topleft[1] + (z * 2), y)] += 1
if __name__ == "__main__":
x = 1024
y = 1024
n = 400
z = 75
start = time.time()
f2(x, y, n, z)
end = time.time()
print("f2:", end - start)
start = time.time()
f3(x, y, n, z)
end = time.time()
print("f3:", end - start)
start = time.time()
f4(x, y, n, z)
end = time.time()
print("f4:", end - start)
start = time.time()
f5(x, y, n, z)
end = time.time()
print("f5:", end - start)
以上代码展示了如何使用不同的方法来处理网格中的数据,并比较了它们的运行时间。可以看到,使用NumPy数组来处理数据是最快的。