2016-11-30 8 views
1

У меня есть функция numpy, которая преобразует 2D-массив координат x, y в плоский массив расстояний между каждой координатой между предыдущими. (См Numpy - transform 2D array of x,y coordinates into flat array of distance between coordinates)Numpy - преобразовать функцию numpy в генератор

input = [[-8081441,5685214], [-8081446,5685216], [-8081442,5685219], [-8081440,5685211], [-8081441,5685214]] 
output = [-8081441, 5685214, 5, -2, -4, -3, -2, 8, 1, -3] 

Благодаря Divakar's answer, у меня есть две Numpy функции, которые делают то, что я хочу

arr = np.asarray(input).astype(int) 
np.hstack((arr[0], (-np.diff(arr, axis=0)).ravel())) 

Другого подхода с нарезкой повторить дифференцирование -

arr = np.asarray(input).astype(int) 
np.hstack((arr[0], (arr[:-1,:] - arr[1:,:]).ravel())) 

Мой вопрос, есть ли способ перенести одну из этих функций numpy в генератор для повышения производительности? Можно ли использовать numpy в генераторе?

+2

Во-первых, берегитесь преждевременной оптимизации, у вас есть функция, которая делает то, что вы хотите. Во-вторых, генераторы действительно не помогут вам здесь. Функции Numpy получают большую часть своей скорости от векторизации, которая требует плотного представления и существенно действует на все элементы массива синхронно. – Erotemic

ответ

2

Генератор Python - это список списков.

In [207]: [i*2 for i in range(3)] 
Out[207]: [0, 2, 4] 
In [208]: (i*2 for i in range(3)) 
Out[208]: <generator object <genexpr> at 0xb6a1ffbc> 
In [209]: list(_) 
Out[209]: [0, 2, 4] 

Вы можете подумать об этом как о ленивом списке. Он не оценивает элементы до тех пор, пока вы не перейдете через него. В Py3 range - генератор (xrange в Py2). Строка In[208] устанавливает генератор, но ничего не оценивает. Так быстро. Но повторение этого в [209] занимает столько же времени, сколько и оригинал в [207]. (Ну, могут быть и незначительные отличия.)

Таким образом, генератор позволяет думать в блоках, как вы со списками, без создания всех промежуточных списков. Это скорее инструмент организации кода, чем один из них.

Я не могу придумать ничего эквивалентного при работе с массивами numpy.

arr=np.array(input) # creates fixed size array from input list 
-np.diff(arr, axis=0) # create another array 

Это создает ряд промежуточных массивов, даже список, и в конечном итоге возвращая массив (и отбрасывая промежуточные):

np.hstack((arr[0],(-np.diff(arr, axis=0)).ravel())) 

Есть ряд простых строительных блоков в этом выражении , Скорость Numpy происходит от выполнения этих шагов в быстро скомпилированном коде. Чтобы получить более высокую скорость, вам придется переписать проблему в C или Cython. В этом коде вы можете выполнять итерацию и выполнять сложные операции на каждом шаге.

Предположительно numpy может выполнить какую-то ленивую оценку, но для этого потребуется кодирование с низким низким уровнем. И нет никакой гарантии, что это приведет к повышению производительности.

Я посмотрел на проблему промежуточных буферов, и будет ли add.at повышение производительности (это не делает) по адресу: https://stackoverflow.com/a/40688879/901925

+0

Благодарим вас за ответ. Наконец, самая эффективная функция использует итератор в генераторе (см. [Этот ответ] (http://codereview.stackexchange.com/a/147908/68343)). Для работы с несколькими большими массивами координат функции Numpy были значительно медленнее. –