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

:)

Другие вопросы по тегам