我可以矢量化这个Python代码吗?

时间:2015-02-21 00:38:48

标签: python numpy vectorization

我是Python的新手,我必须尽快实现#34;"此代码的版本。

s="<%dH" % (int(width*height),)
z=struct.unpack(s, contents)

heights = np.zeros((height,width))
for r in range(0,height):
    for c in range(0,width):
        elevation=z[((width)*r)+c]
        if (elevation==65535 or elevation<0 or elevation>20000):
            elevation=0.0

        heights[r][c]=float(elevation)

我已经阅读了一些python矢量化问题......但我认为它不适用于我的情况。大多数问题都是使用np.sum而不是for loops。我想我有两个问题:

  1. 是否有可能加快此代码......我认为heights[r][c]=float(elevation)是瓶颈所在。我需要找一些Python计时命令来确认这一点。
  2. 如果可以加速此代码。我有什么选择?我看到有些人推荐cythonpypyweave。我可以在C中更快地做到这一点,但是这段代码也需要生成图,所以我想坚持使用Python,所以我可以使用matplotlib

1 个答案:

答案 0 :(得分:5)

正如您所提到的,使用numpy编写快速代码的关键涉及向量化,并将工作推送到快速C级例程而不是Python循环。通常的方法似乎相对于原始代码改进了十倍左右:

def faster(elevation, height, width):
    heights = np.array(elevation, dtype=float)
    heights = heights.reshape((height, width))
    heights[(heights < 0) | (heights > 20000)] = 0
    return heights

>>> h,w = 100, 101; z = list(range(h*w))
>>> %timeit orig(z,h,w)
100 loops, best of 3: 9.71 ms per loop
>>> %timeit faster(z,h,w)
1000 loops, best of 3: 641 µs per loop
>>> np.allclose(orig(z,h,w), faster(z,h,w))
True

即使是z更长的比例,这个比率也似乎有效:

>>> h,w = 1000, 10001; z = list(range(h*w))
>>> %timeit orig(z,h,w)
1 loops, best of 3: 9.44 s per loop
>>> %timeit faster(z,h,w)
1 loops, best of 3: 675 ms per loop