views:

105

answers:

5

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
A: 

You can probably do this even without looping, although off the top of my head I can't come up with exactly how. This, however, is something I think will run a little faster.

[row,ll] = size(Data);

for loop = 1 : row
    if Data(loop,1) == 0
        Data2(loop,1) = (-1)^row;
    else
        Data2(loop,1) = 3*(-1)^row;
    end
end

Does it?

If you'd post your data as a txt file somewhere publicly accessible, I could try it out on my machine.

Tomas Lycken
If `Data = [1 0 1 0 1 0 1 0]` then the "symbols" are not distributed equally.
KennyTM
True - I guess I was a little too fast...
Tomas Lycken
A: 
[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
peachykeen
I don't see a significant difference in the performance, when using your code. So, it didn't really work.
HH
A: 

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.

Conspicuous Compiler
Your idea is good, but I will increase the symbol pattern to more than 1 and 3 in the latter part of my project.
HH
@HH: So long as there is a simple mapping of input values to output symbols, you can make a linear equation which will produce the result (and which can be vectorized efficiently by MATLAB), but it sounds like you have a sufficient solution already by using preallocation.
Conspicuous Compiler
+2  A: 

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 1s and 0s.

High Performance Mark
+7  A: 

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.

Jacob