简体   繁体   中英

Help in optimizing a for loop in matlab

I have a 1 by N double array consisting of 1 and 0. I would like to map all the 1 to symbol '-3' and '3' and all the 0 to symbol '-1' and '1' equally. Below is my code. As my array is approx 1 by 8 million, it is taking a very long time. How to speed things up?

[row,ll] = size(Data);
sym_zero = -1;
sym_one = -3;
for loop = 1 : row
    if Data(loop,1) == 0
        Data2(loop,1) = sym_zero;
                     if sym_zero == -1
                         sym_zero = 1;
                     else
                         sym_zero = -1;
                     end
    else
        Data2(loop,1) = sym_one;
                     if sym_one == -3
                         sym_zero = 3;
                     else
                         sym_zero = -3;
                     end
    end
end

Here's a very important MATLAB optimization tip.

Preallocate!

Your code is much faster with a simple preallocation. Just add

Data2 = zeros(size(Data));
for loop = 1: row 
...

before your for loop.

On my computer your code with preallocation terminated in 0.322s , and your original code is still running. I removed my original solution since yours is pretty fast with this optimization :).

Also since we're talking about MATLAB, it's faster to work on column vectors.

Hope you can follow this and I hope that I have understood your code correctly:

nOnes = sum(Data);
nZeroes = size(Data,2) - nOnes;

Data2(find(Data)) = repmat([-3 3],1,nOnes/2)
Data2(find(Data==0)) = repmat([-1 1],1,nZeroes/2)

I'll leave it to you to deal with the odd 1 s and 0 s.

So, disregarding negative signs, the equation for the output item Data2[loop,1] = Data[loop,1]*2 + 1. So why not first do that using a simple multiply-- that should be fast since it can be vectorized. Then create an array of half the original array length of 1s, half the original array length of -1s, call randperm on that. Then multiply by that. Everything's vectorized and should be much faster.

[row,ll] = size(Data);
sym_zero = -1;
sym_one = -3;
for loop = 1 : row
    if ( Data(loop,1) ) // is 1
        Data2(loop,1) = sym_one;
        sym_one = sym_one * -1; // flip the sign
    else
        Data2(loop,1) = sym_zero;
        sym_zero = sym_zero * -1; // flip the sign
    end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM