Matlab упаковывает биты в байтовый массив
В Matlab я пытаюсь упаковать произвольные целые числа без знака (например, массив 3-битных целых чисел) в массив uint8. Учитывая подсказку, я могу сгенерировать код, который работает для "маленьких" массивов (скажем, 10000 элементов), но он потребляет всю память для больших массивов (например, 16 миллионов элементов). Код, который я использую ниже, заимствуя из предыдущих сообщений:
function x_bytes = stuff_bits(x, n)
r = dec2bin(x,n); % bitstring for each uint in x
s = reshape(r',[],1); % one continuous string of bits
t = reshape(str2num(s),8,[])'; % array of 8-bit numbers (stuffed)
u = t*(2.^(size(t,2)-1:-1:0))'; % array of bytes representing all the bits stuffed together
x_bytes = uint8(u); % should be compressed byte stream
end
Я понимаю, что беру уинт, преобразуя его в строку, а затем преобразуя обратно в немного; Я также читал, что dec2bin не очень эффективен.
Когда я пытаюсь сделать это с 16-миллиметровыми элементами (на 64-битной Windows-коробке с 8 ГБ памяти), вся память используется. Мля. Поэтому я перебираю подразделы, и для завершения 16-ти элементных элементов требуется около 10 минут. Итак, что-то очень неэффективно.
У кого-нибудь есть лучший способ генерировать битовые строки, такие как Python BitArray?
Спасибо,
2 ответа
Кажется, что это похоже на этот и этот
На первом этапе было предложено использовать dec2bitvec внутри цикла for. Это может быть достаточно для вас (хотя и медленно).
Второй предлагает создать таблицу поиска, используя bitget, а затем использовать ее (вместо использования dec2bit или dec2bitvec)
Вы можете попытаться использовать что-то "в середине".
B = 3; % Number of bits per int.
A = randi(7, 16000000, 1); % 16M random elements between 1 and 7 (3bits).
tic
% get each group of bits in a column of K.
K = cell2mat(arrayfun(@(bit)bitget(A, B+1-bit), 1:B, 'UniformOutput', 0))';
% reshape to have them in 8 packs
K = reshape(K, [8, numel(K)/8])';
% get the uint8 vec.
U = K*(2.^(size(K,2)-1:-1:0))';
toc
Моя прошла через 3,5 секунды. (Win8 64 бит, i5 4 Гб оперативной памяти)
Вместо создания таблицы поиска этот код создает матрицу (K) со значениями битов каждого целого числа (хранится в столбцах), изменяет ее форму (для создания 8-разрядного значения), а затем использует ту же математику, которую вы использовали ранее для создания uint8. вектор.
Это код, который я создал для преобразования матрицы битов в n-битные числа:
function [ uD10 ] = bits_to_n_bit_integers( A, n)
%bits_to_n_bit_integersTurns vector matrix of bits in A into a vector matrix of
%n bits long numbers.
%B is 1 for a bit matrix
% Detailed explanation goes here
B = 1;
% get each group of bits in a column of K.
K = cell2mat(arrayfun(@(bit)bitget(A, B+1-bit), 1:B, 'UniformOutput', 0))';
%make sure there is multiple of B
K = K(:);
while ~(mod(numel(K),n) == 0)
K = [0;K];
end
K = K(:);
% reshape to have them in 8 packs
K = reshape(K, [n, numel(K)/n])';
% get the uint8 vec.
UD = K*(2.^(size(K,2)-1:-1:0))';
uD10=bi2de(K);
end
:)