Учитывая, что MATLAB uint32 должен интерпретироваться как битовая строка, каков эффективный и краткий способ подсчета количества ненулевых битов в строке?
У меня есть рабочий, наивный подход, который повторяется, но это слишком медленно для моих нужд. (Реализация C ++ с использованием 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 весовых расчетов. Мой код C ++, использующий count () из std :: bitset, делает это за секунду.
Обновление № 2
Вот таблица времени выполнения техник, которые я уже пробовал. Я буду обновлять его по мере поступления дополнительных идей / предложений.
Vectorized Scheiner algorithm => 2.243511 sec
Vectorized Naive bitget loop => 7.553345 sec
Kernighan algorithm => 17.154692 sec
length( find( bitget( val, 1:32 ) ) ) => 67.368278 sec
nnz( bitget( val, 1:32 ) ) => 349.620259 sec
Justin Scheiner's algorithm, unrolled loops => 370.846031 sec
Justin Scheiner's algorithm => 398.786320 sec
Naive bitget loop => 456.016731 sec
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
Комментарий :
Развернутая в цикле версия алгоритма Шайнера выглядит следующим образом:
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));