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 randomdef 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 = inputtopleft = (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.randrangeinc = (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)] += 1if __name__ == "__main__":x = 1024y = 1024n = 400z = 75start = 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数组来处理数据是最快的。