Эффективная нарезка матриц с помощью NumPy - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь умножить субматрицу на субвектор.Кажется, что такое умножение должно быть быстрее, чем умножение всей матрицы на весь вектор, но измерения времени говорят об обратном:

B = np.random.randn(26200, 2000)
h = np.random.randn(2000)
%time z = B @ h
CPU times: user 56 ms, sys: 4 ms, total: 60 ms
Wall time: 29.4 ms

%time z = B[:, :256] @ h[:256]
CPU times: user 44 ms, sys: 28 ms, total: 72 ms
Wall time: 54.5 ms 

Результаты с% timeit:

%timeit z = B @ h
100 loops, best of 3: 18.8 ms per loop

%timeit z = B[:, :256] @ h[:256]
10 loops, best of 3: 38.2 ms per loop

Запуск этогоеще раз:

%timeit z = B @ h
10 loops, best of 3: 18.7 ms per loop 

%timeit z = B[:, :256] @ h[:256]
10 loops, best of 3: 36.8 ms per loop

Может быть, есть какой-нибудь эффективный способ сделать это с помощью numpy, или мне может понадобиться использовать, например, tenserflow, чтобы сделать это нарезание эффективным?

1 Ответ

0 голосов
/ 23 декабря 2018

Это проблема расположения памяти и времени доступа.По умолчанию массивы хранятся построчно, как в C (order='C'). Вы можете хранить столбец данных за столбцом, как в Fortran (order='F'), что более совместимо с вашей ограниченной проблемой, поскольку вы выбираететолько несколько столбцов.

Иллюстрационная:

In [107]: BF=np.asfortranarray(B)

In [108]: np.equal(B,BF).all()
Out[108]: True


In [110]: %timeit B@h
78.5 ms ± 20.2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [111]: %timeit BF@h
89.3 ms ± 7.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [112]: %timeit B[:,:256]@h[:256]
150 ms ± 18.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [113]: %timeit BF[:,:256]@h[:256]
10.5 ms ± 893 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Таким образом, время выполнения следует за размером.

...