我有一组来自传感器的32位二进制值。我必须形成这些值的所有可能组合,然后将它们转换为十进制值。
如果传入的行数超过80000 - 90000,则代码速度会非常慢。运行需要120分钟。
我想优化这段代码,因为3 For循环和最内层循环中的函数正在减慢我的算法速度。有没有机会我可以消除一些For循环并用矢量化代替它们来加速这个过程。
b1 = [0 1 0 1 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 1];
b2 = [0 1 0 1 0 1 1 1 1 1 1 0 1 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 1];
b3 = [0 1 0 1 0 1 0 1 1 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1];
b4 = [0 1 0 1 0 1 1 1 1 1 0 1 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 1];
b5 = [0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1];
FullVector = [b1;b2;b3;b4;b5];
for Idx = 1:size(FullVector,1)
k = 1;
MinLength = 4;
MaxLength = 8;
StepSize = 2;
for StartByte = 1:8
for StartBit = 1:8
for SignalLength = MinLength:StepSize:MaxLength
DecimalVals.s(Idx,k) = BitCombinations(FullVector,StartByte,StartBit,SignalLength);
k = k+1;
end
end
end
end
功能:
function decimal = BitCombinations(ByteArray,Sbyte,Sbit,lengthSignal)
%function extracts the required bits from a byte array and
%returns the decimal equivalent of the bits.
%Inputs:
%Sbyte - Starting byte
%Sbit - Starting bit in the given byte
%length - length of bits to be extracted
%Output:
%dec - Returns the dec
startbit_pos = ((Sbyte-1)*8+Sbit);
endbit_pos = ((Sbyte-1)*8+Sbit+lengthSignal-1);
if endbit_pos <= 64
extractedbits = ByteArray(startbit_pos:endbit_pos);
extractedbits = fliplr(extractedbits);
decimal = bi2de(extractedbits);
else
decimal = NaN;
end
end
答案 0 :(得分:1)
您应该使用以下代码示例预先分配结果矩阵DecimalVals
:
b1 = repmat([0 1 0 1 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 1],10000,1);
b2 = repmat([0 1 0 1 0 1 1 1 1 1 1 0 1 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 1],10000,1);
b3 = repmat([0 1 0 1 0 1 0 1 1 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1],10000,1);
b4 = repmat([0 1 0 1 0 1 1 1 1 1 0 1 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 1],10000,1);
b5 = repmat([0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1],10000,1);
FullVector = [b1;b2;b3;b4;b5];
MinLength = 4;
MaxLength = 8;
StepSize = 2;
% Preallocation of the result struct
noOfValues = (((MaxLength - MinLength) / 2) + 1) * MaxLength * MaxLength;
DecimalVals = zeros(size(FullVector,1),noOfValues);
for Idx = 1:size(FullVector,1)
k = 1;
for StartByte = 1:MaxLength
for StartBit = 1:MaxLength
for SignalLength = MinLength:StepSize:MaxLength
DecimalVals(Idx,k) = BitCombinations(FullVector,StartByte,StartBit,SignalLength);
k = k+1;
end
end
end
end
结果(在我的机器上):
没有预先分配的时间消耗:560秒
时间消耗与预分配:300秒
此外,请使用MATLAB Profiler(使用“运行和时间”启动脚本)来分别识别哪个函数需要花费大部分时间并将函数/行添加到您的问题中。
不幸的是,我无法访问通信系统工具箱的功能,所以我使用了文件交换中的函数bi2de
。在这个版本中,有一种错误检查,需要花费很多时间: ~230秒
答案 1 :(得分:0)
除了预先分配数组之外,你可以做的另一件事是不使用fliplr。看一下这段代码
tic
N = 10000;
A = [1:N];
for i = 1:N/2
b = A(N-i+1:-1:i);
end
toc
b = [];
tic
for i = 1:N/2
b = fliplr(A(i:N-i+1));
end
toc
经过的时间是0.060007秒。 经过的时间是0.118267秒。
因此,fliplr的使用速度要慢2倍,而不是简单地使用&#34;向后&#34;索引。我非常确定你可以通过自己的bi2de功能获得一些特定于你的问题的东西。
我尝试了这个,虽然没有检查它的效率,但也许你可以将它用于你的目的
function values = myBi2Dec(byte,signalLengths)
persistent indexes
if isempty(indexes)
% Find the matrix indexes for this
indexes = [];
for iBit = 1:8
for iSL = signalLengths
if iBit+iSL-1<=8
indexes = [indexes;sub2ind([8,8],iBit,iBit+iSL-1)];
end
end
end
end
% Lets get the cumulative value
cumB2D = cumBi2Dec(byte);
% We already calculated their position, so simply return them
values = cumB2D(indexes);
function cumB2D = cumBi2Dec(byte)
persistent B2D
if isempty(B2D)
B2D = zeros(8,8);
tmp = 2.^[0:7];
for i = 1:8
B2D(i,i:8) = tmp(1:8-(i-1));
end
end
cumB2D = cumsum(repmat(fliplr(byte),8,1).*B2D,2);
然后尝试,例如,myBi2Dec([0,0,0,0,1,1,1,1],[4:2:8])