簡體   English   中英

在 Matlab 中使用矢量化而不是“for 循環”

[英]Using vectorization instead of a 'for Loop' in Matlab

我有一組來自傳感器的 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

您應該使用以下代碼示例預先分配結果矩陣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 探查器(通過使用“運行和時間”啟動腳本)來確定瓶頸,分別是哪個函數花費最多時間並將函數/行添加到您的問題中。

不幸的是,我無法訪問通信系統工具箱的功能,所以我使用了文件交換中的功能bi2de 在這個版本中,有一種錯誤檢查,需要很多時間: ~230秒

除了預先分配數組之外,您還可以做的另一件事是不使用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 倍左右,而不是簡單地使用“向后”索引。 我很確定您也可以通過制作自己的特定於您的問題的 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])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM