Учитывая, что MATLAB uint32 интерпретируется как битовая строка, что является эффективным и сжатым способом подсчета количества ненулевых битов в строке?
У меня есть рабочий, наивный подход, который перебирает биты, но это слишком медленно для моих нужд. (Реализация С++ с использованием std:: bitset count() выполняется почти мгновенно).
Я нашел довольно приятную страницу с перечислением различных методов подсчета бит, но я надеюсь, что есть простой способ MATLAB-esque.
http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
Обновление # 1
Просто реализован алгоритм Брайана Кернигана следующим образом:
w = 0;
while ( bits > 0 )
bits = bitand( bits, bits-1 );
w = w + 1;
end
Производительность все еще дерьмовая, более 10 секунд, чтобы вычислить только 4096 ^ 2 весовых расчетов. Мой код на С++, использующий count() из std:: bitset, делает это в течение субсекунды.
Обновление # 2
Вот таблица времени выполнения тех методов, которые я пробовал до сих пор. Я обновлю его, когда получаю дополнительные идеи/предложения.
Векторизованный алгоритм Шайнера => 2.243511 с Векторизованный цикл наивного бита => 7.553345 сек. Алгоритм Кернигана => 17.154692 сек. length (find (bitget (val, 1:32))) => 67.368278 sec nnz (битгет (val, 1:32)) => 349.620259 сек Джастин Шайнер, развернутые петли => 370.846031 сек Алгоритм Джастина Шайнера => 398.786320 сек. Наивный цикл битги => 456.016731 сек. sum (dec2bin (val) == '1') => 1069.851993 sec
Комментарий: Функция dec2bin() в MATLAB, кажется, очень плохо реализована. Он работает очень медленно.
Комментарий: алгоритм "алгоритм наивного бита" реализован следующим образом:
w=0;
for i=1:32
if bitget( val, i ) == 1
w = w + 1;
end
end
Комментарий: Развернутая в петле версия алгоритма Scheiner выглядит следующим образом:
function w=computeWeight( val )
w = val;
w = bitand(bitshift(w, -1), uint32(1431655765)) + ...
bitand(w, uint32(1431655765));
w = bitand(bitshift(w, -2), uint32(858993459)) + ...
bitand(w, uint32(858993459));
w = bitand(bitshift(w, -4), uint32(252645135)) + ...
bitand(w, uint32(252645135));
w = bitand(bitshift(w, -8), uint32(16711935)) + ...
bitand(w, uint32(16711935));
w = bitand(bitshift(w, -16), uint32(65535)) + ...
bitand(w, uint32(65535));