Подтвердить что ты не робот

Python/Numpy - Маскированные массивы очень медленные

Есть ли что-нибудь, что я могу сделать, чтобы ускорить маскирование массивов в numpy? У меня была ужасно неэффективная функция, которую я повторно написал для использования маскированных массивов (где я мог просто маскировать строки, а не делать копии и удалять строки, как я это делал). Тем не менее, я был потрясен, обнаружив, что функция маскирования была на 10 раз медленнее, потому что маскированные массивы намного медленнее.

В качестве примера возьмите следующее (для маскировки более 6 раз медленнее):

import timeit
import numpy as np
import numpy.ma as ma

def test(row):
   return row[0] + row[1]

a = np.arange(1000).reshape(500, 2)
t = timeit.Timer('np.apply_along_axis(test, 1, a)','from __main__ import test, a, np')
print round(t.timeit(100), 6)

b = ma.array(a)
t = timeit.Timer('ma.apply_along_axis(test, 1, b)','from __main__ import test, b, ma')
print round(t.timeit(100), 6)
4b9b3361

Ответ 1

Я понятия не имею, почему маскированные функции массива перемещаются так медленно, но поскольку кажется, что вы используете маску для выбора строк (в отличие от отдельных значений), вы можете создать обычный массив из замаскированных строк и использовать вместо этого: np:

b.mask = np.zeros(500)
b.mask[498] = True
t = timeit.Timer('c=b.view(np.ndarray)[~b.mask[:,0]]; np.apply_along_axis(test, 1, c)','from __main__ import test, b, ma, np')
print round(t.timeit(100), 6)

Еще лучше, не используйте маскированные массивы; просто сохраните свои данные и массив маски 1D в виде отдельных переменных:

a = np.arange(1000).reshape(500, 2)
mask = np.ones(a.shape[0], dtype=bool)
mask[498] = False
out = np.apply_along_axis(test, 1, a[mask])

Ответ 2

EDIT: я неправильно тестировал его, используя np.apply_along_axis вместо np.ma.apply_along_axis, извините. Поэтому я подтверждаю, что версия маскированного массива более чем в 5 раз медленнее также на Linux/numpy 1.5.1

In [16]: %timeit np.apply_along_axis(test, 1, a)
100 loops, best of 3: 15.3 ms per loop

In [17]: %timeit np.apply_along_axis(test, 1, b)
100 loops, best of 3: 15.3 ms per loop

In [12]: %timeit np.ma.apply_along_axis(test, 1, b)
10 loops, best of 3: 80.8 ms per loop

In [18]: np.__version__
Out[18]: '1.5.1'