如何进一步缩短Python性能

2024-05-29 15:21:17 浏览数 (2)

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编写的示例代码来处理网格中的数据:

代码语言:javascript复制
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数组来处理数据是最快的。

0 人点赞