numpy: логическое индексирование и использование памяти - PullRequest
7 голосов
/ 11 мая 2011

Рассмотрим следующий numpy код:

A[start:end] = B[mask]

Здесь:

  • A и B - двумерные массивы с одинаковым количеством столбцов;
  • start и end являются скалярами;
  • mask является одномерным логическим массивом;
  • (end - start) == sum(mask).

В принципе, вышеуказанная операция может быть выполнена с использованием O(1) временного хранилища, путем копирования элементов B непосредственно в A.

Это то, что на самом деле происходит на практике, или numpy создает временный массив для B[mask]? Если последнее, есть ли способ избежать этого, переписав утверждение?

Ответы [ 2 ]

3 голосов
/ 11 мая 2011

Линия

A[start:end] = B[mask]

- согласно определению языка Python - сначала вычислит правую часть, получив новый массив, содержащий выбранные строки B и занимающий дополнительную память. Мне известно, что наиболее эффективный способ чистого Python избежать этого - использовать явный цикл:

from itertools import izip, compress
for i, b in izip(range(start, end), compress(B, mask)):
    A[i] = b

Конечно, это будет намного менее затратно по времени, чем ваш оригинальный код, но он использует только O (1) дополнительной памяти. Также обратите внимание, что itertools.compress() доступен в Python 2.7 или 3.1 или выше.

2 голосов
/ 11 мая 2011

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

...