Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
optimizing a for loop

Subject: optimizing a for loop

From: Daphne

Date: 23 Dec, 2008 11:34:03

Message: 1 of 5


I have two concentric for loops and would like to vectorize at least one of them for time optimization. Can anyone help with this one:

% m is from the external loop
c=[0.5 1 2 4 8];
for k=1:length(q)
   A(m,k) = sum( abs(B).^c(k) );
end

Any ideas will be appreciated.

Thanks!
Daphne

Subject: optimizing a for loop

From: Walter Roberson

Date: 23 Dec, 2008 17:18:50

Message: 2 of 5

Daphne wrote:
> I have two concentric for loops and would like to vectorize at least one of them for time optimization. Can anyone help with this one:

> % m is from the external loop
> c=[0.5 1 2 4 8];
> for k=1:length(q)
> A(m,k) = sum( abs(B).^c(k) );
> end

It appears to me that bsxfun would be usable in that situation -- but you would have to
test to see if it was any faster.

absB = abs(B) .'; %note transpose
c = [0.5 1 2 4 8];
A(m,:) = sum(bsxfun(@power, absB, c));

or more simply,

A(m,:) = sum(bsxfun(@power, abs(B) .', [0.5 1 2 4 8]));

> Any ideas will be appreciated.

Note that in your loop, abs(B) is done for each iteration. If you do keep the loop
structure, then you should do the abs() once outside of the loop and use that inside
the loop.

Also, the bsxfun solution I gave above is dependant upon length(q) being the same as
length(c). If length(q) is longer than length(c) you have a problem. If length(q) is
not necessary the same as the length of c but could be shorter, you could adjust as

c = [0.5 1 2 4 8];
A(m,:) = sum(bsxfun(@power, abs(B) .', c(1:length(q)) );

--
.signature note: I am now avoiding replying to unclear or ambiguous postings.
Please review questions before posting them. Be specific. Use examples of what you mean,
of what you don't mean. Specify boundary conditions, and data classes and value
relationships -- what if we scrambled your data or used -Inf, NaN, or complex(rand,rand)?

Subject: optimizing a for loop

From: Daphne

Date: 24 Dec, 2008 09:38:04

Message: 3 of 5


Thanks for the quick response.

You were correct to assume that c,q were the same size. My bad (c=q).
I had to upgrade to 2007b to use the bsxfun and then found that if the B and c are not the same length it will not work?
Ended up combining the approaches, as you had suggested, so the final code is:

absB = abs(B);
for k=1:length(c)
  A(m,k) = sum (bsxfun ( @power, absB.', c(k) ) );
end

The run-time difference is:
For the original: Elapsed time is 0.105037 seconds.
Using the bsxfun: Elapsed time is 0.073175 seconds.

Definitely worth it for long calculations, thanks!!

Daphne


Walter Roberson <roberson@hushmail.com> wrote in message <q394l.707$mE3.99@newsfe14.iad>...
> Daphne wrote:
> > I have two concentric for loops and would like to vectorize at least one of them for time optimization. Can anyone help with this one:
>
> > % m is from the external loop
> > c=[0.5 1 2 4 8];
> > for k=1:length(q)
> > A(m,k) = sum( abs(B).^c(k) );
> > end
>
> It appears to me that bsxfun would be usable in that situation -- but you would have to
> test to see if it was any faster.
>
> absB = abs(B) .'; %note transpose
> c = [0.5 1 2 4 8];
> A(m,:) = sum(bsxfun(@power, absB, c));
>
> or more simply,
>
> A(m,:) = sum(bsxfun(@power, abs(B) .', [0.5 1 2 4 8]));
>
> > Any ideas will be appreciated.
>
> Note that in your loop, abs(B) is done for each iteration. If you do keep the loop
> structure, then you should do the abs() once outside of the loop and use that inside
> the loop.
>
> Also, the bsxfun solution I gave above is dependant upon length(q) being the same as
> length(c). If length(q) is longer than length(c) you have a problem. If length(q) is
> not necessary the same as the length of c but could be shorter, you could adjust as
>
> c = [0.5 1 2 4 8];
> A(m,:) = sum(bsxfun(@power, abs(B) .', c(1:length(q)) );
>
> --
> .signature note: I am now avoiding replying to unclear or ambiguous postings.
> Please review questions before posting them. Be specific. Use examples of what you mean,
> of what you don't mean. Specify boundary conditions, and data classes and value
> relationships -- what if we scrambled your data or used -Inf, NaN, or complex(rand,rand)?

Subject: optimizing a for loop

From: Walter Roberson

Date: 24 Dec, 2008 15:10:56

Message: 4 of 5

Daphne wrote:

> bsxfun and then found that if the B and c are not the same length it will not work?

You must have missed the transpose. For your problem, one input to bsxfun should
be a row vector and the other input should be a column vector. It doesn't matter which
is the row and which is the column: if B is the row and C is the column, the result would
be the transpose of the case where B is the column and C is the row. I already took
the choice of which should be row or column into account when I posted the previous code.

Quoting my previous solution:

absB = abs(B) .'; %note transpose
c = [0.5 1 2 4 8];
A(m,:) = sum(bsxfun(@power, absB, c));

However if B is already a column vector do not put the transpose on the end
of the first line.

Your hybrid solution of doing bsxfun in a loop is going to be slower than
doing bsxfun the way I describe: when you pass in c(k) as the only thing
for the final argument, you waste the power of bsxfun, and you would probably
find

absB = abs(B);
for k=1:length(c)
  A(m,k) = sum (absB .^ c(k));
end

to be faster. This is similar to your original solution except it pulls the
absolute value taking out of the loop.


Consider your hybrid solution again:

absB = abs(B);
for k=1:length(c)
  A(m,k) = sum (bsxfun ( @power, absB.', c(k) ) );
end

You are taking the transpose of absB each time through the loop. That's a
waste of time. Pull it out:

absB = abs(B) .';
for k=1:length(c)
  A(m,k) = sum (bsxfun ( @power, absB, c(k) ) );
end

This should be faster than your hybrid version, slower than the loop that does
not use bsxfun at all, and my original solution would -probably- be fastest.

--
.signature note: I am now avoiding replying to unclear or ambiguous postings.
Please review questions before posting them. Be specific. Use examples of what you mean,
of what you don't mean. Specify boundary conditions, and data classes and value
relationships -- what if we scrambled your data or used -Inf, NaN, or complex(rand,rand)?

Subject: optimizing a for loop

From: Daphne

Date: 25 Dec, 2008 08:29:04

Message: 5 of 5


Thanks again!

I was mixing up my row-column settings.

A small comparison between the different approaches

The loop with bsxfun (abs, transpose outside): Elapsed time is 0.051334 seconds.
absB = abs(B) .';
for k=1:length(c)
A(m,k) = sum (bsxfun ( @power, absB, c(k) ) );
end

The basic loop (abs outside): Elapsed time is 0.054493 seconds.
absB = abs(B);
for k=1:length(c)
A(m,k) = sum (absB .^ c(k));
end

The vectorized form: Elapsed time is 0.049022 seconds.
absB = abs(B) .'; %note transpose
c = [0.5 1 2 4 8];
A(m,:) = sum(bsxfun(@power, absB, c));

Another run gave
Elapsed time is 0.051442 seconds.
Elapsed time is 0.054468 seconds.
Elapsed time is 0.055072 seconds.
So there is really not that much of a difference between the approaches per calculation. However, it does seem that the two loop options are stable in calculation time, while the vectorized form changes between cases.

to study this a bit more I let my entire loop run, and averaged the times for all of them. The calculcations become shorter as my loops progress, hence the averages are much lower than the numbers above.
1. bsxfun loop 0.0158 +- 0.009 total time 15.6885
2. basic loop 0.0163 +- 0.0093 16.0933
3. vectorized bsxfun 0.0166 +- 0.0097 16.4012
Interesting. The bsxfun is good in any case.

Thanks again for your help.

Daphne


Walter Roberson <roberson@hushmail.com> wrote in message <phs4l.4344$hr3.4255@newsfe01.iad>...
> Daphne wrote:
>
> > bsxfun and then found that if the B and c are not the same length it will not work?
>
> You must have missed the transpose. For your problem, one input to bsxfun should
> be a row vector and the other input should be a column vector. It doesn't matter which
> is the row and which is the column: if B is the row and C is the column, the result would
> be the transpose of the case where B is the column and C is the row. I already took
> the choice of which should be row or column into account when I posted the previous code.
>
> Quoting my previous solution:
>
> absB = abs(B) .'; %note transpose
> c = [0.5 1 2 4 8];
> A(m,:) = sum(bsxfun(@power, absB, c));
>
> However if B is already a column vector do not put the transpose on the end
> of the first line.
>
> Your hybrid solution of doing bsxfun in a loop is going to be slower than
> doing bsxfun the way I describe: when you pass in c(k) as the only thing
> for the final argument, you waste the power of bsxfun, and you would probably
> find
>
> absB = abs(B);
> for k=1:length(c)
> A(m,k) = sum (absB .^ c(k));
> end
>
> to be faster. This is similar to your original solution except it pulls the
> absolute value taking out of the loop.
>
>
> Consider your hybrid solution again:
>
> absB = abs(B);
> for k=1:length(c)
> A(m,k) = sum (bsxfun ( @power, absB.', c(k) ) );
> end
>
> You are taking the transpose of absB each time through the loop. That's a
> waste of time. Pull it out:
>
> absB = abs(B) .';
> for k=1:length(c)
> A(m,k) = sum (bsxfun ( @power, absB, c(k) ) );
> end
>
> This should be faster than your hybrid version, slower than the loop that does
> not use bsxfun at all, and my original solution would -probably- be fastest.
>
> --
> .signature note: I am now avoiding replying to unclear or ambiguous postings.
> Please review questions before posting them. Be specific. Use examples of what you mean,
> of what you don't mean. Specify boundary conditions, and data classes and value
> relationships -- what if we scrambled your data or used -Inf, NaN, or complex(rand,rand)?

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us