как уменьшить требования к памяти функции Matlab 'найти'? - PullRequest
1 голос
/ 11 ноября 2010

У меня есть строка кода в Matlab, которая гласит:

  output = find(input);

, где вектор столбца "output" содержит все индексы в векторе столбца "input", чьи элементы отличны от нуля.Например, если:

 input = [1 3 4 0 0 2 0];

, то результат: output = find (input);будет:

 output = 
     1
     2
     3
     6

, соответствующий 1-му ("1"), 2-му ("3"), 3-му ("4") и 6-му ("2") индексам массива "input", которыеотличны от нуля.

Поскольку мой «входной» массив очень большой, эта строка кода потребляет всю мою локальную оперативную память плюс огромную часть виртуальной памяти, что приводит к замедлению работы системы.

Кто-нибудь знает хороший способ (или каким-либо образом) уменьшить требования к памяти для такой операции?Я думал о том, чтобы поместить код "find" в цикл, но поскольку размер "output" массива (и, следовательно, индексация этого массива) зависит от результата операции "find", я не понимаю, как это возможноСделай так.Закончились идеи.

Заранее спасибо за любые комментарии / предложения.-gkk

Ответы [ 2 ]

3 голосов
/ 11 ноября 2010

Если у вас больше ненулевых значений, чем нулей, возможно, вы можете работать с дополнением, то есть: output=find(input==0) вместо значения по умолчанию, которое эквивалентно output=find(input~=0)

Также вы можете использовать логическоеиндексирование, сравните:

>> output1 = find(input);
>> output2 = (input~=0);
>> whos output*
  Name         Size            Bytes  Class      Attributes

  output1      1x4                32  double               
  output2      1x7                 7  logical    

обратите внимание, как оно хранится как вектор «логических значений», который составляет один байт каждый (против 8 байтов для «двойного»)

2 голосов
/ 11 ноября 2010

Если у вас достаточно ОЗУ для хранения массива такого же размера, как input, вы можете заменить вызов find на

output = 1:length(input);
output = output(input~=0);

Если input имеет менее 2 ^ 32-1 элемент, вы можете инициализировать его как uint32, и, таким образом, дополнительно сэкономить память.

Лучшим способом может быть преобразование массива input в sparse , который экономит память, еслиinput содержит много нулей, а затем используйте find для этого, то есть

input = sparse(input);
output = find(input);

РЕДАКТИРОВАТЬ

Для выполнения операции findпо частям я бы сделал следующее:

nIn = length(input);
blockLength = 100000;
nBlocks = ceil(nIn/blockLength); %# work in chunks of 100k entries
out = cell(nBlocks,1);
for i=1:nBlocks
   out{i} = (i-1)*blockLength+1:i*blockLength; %# assign as your favorite integer format here
   out{i} = out{i}(input(out{i})~=0);
end
out = cat(1,out{:});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...