2015-02-21 10 views
2

Я как бы новичок в Python, и мне нужно реализовать «быструю» версию этого кода.Могу ли я векторизовать этот код Python?

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. Если возможно ускорить этот код. Какие у меня варианты? Я видел, как некоторые люди рекомендуют cython, pypy, weave. Я мог бы сделать это быстрее в C, но этот код также должен генерировать графики, поэтому я хотел бы придерживаться Python, поэтому я могу использовать matplotlib.
+1

[RunSnakeRun] (HTTP://www.vrplumber.com/programming/runsnakerun/) - отличный просмотрщик профилей Python, который показывает использование времени в формате treemap. Получите профиль, повернув 'dostuff()' в 'profile.runctx ('dostuff()', globals(), locals(), filename = 'out.profile')' –

ответ

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 
+1

Ударьте меня! Вы также можете захотеть прочитать данные с использованием 'np.fromstring (contents, dtype = np.uint16)' (или 'fromfile', если оно изначально находится в файле) вместо' struct.unpack'. Это обычно значительно быстрее, чем распаковка в кортеж с использованием 'struct', а затем преобразование в массив для больших наборов данных. –

+0

спасибо! это действительно полезно! – jti107

Смежные вопросы