Re: Speeding up code
- To: mathgroup at smc.vnet.net
- Subject: [mg100437] Re: Speeding up code
- From: David Bailey <dave at removedbailey.co.uk>
- Date: Wed, 3 Jun 2009 05:29:23 -0400 (EDT)
- References: <h02vo6$8ek$1@smc.vnet.net> <h050kr$abg$1@smc.vnet.net>
pfalloon wrote:
> On Jun 2, 8:43 pm, bori... at sas.upenn.edu wrote:
>> Hello all,
>>
>> I need some advise on speeding up code. Here is a section that is executed more
>> than 100000 times during my simulations. Currently it takes about 0.06s per
>> execution which is about 80% of the total time for the simulation. The
>> subsection MITime itself takes 0.03s out of those 0.06s. All variables not
>> defined in this section are predefined. Anyone have suggestions?
>>
>> MDTime = First[
>> Timing[
>> yps = Table[(ys[[i]] + ys[[i - 1]])/2, {i, 2, ngrid}];
>> yms = Table[(ys[[i]] - ys[[i - 1]]), {i, 2, ngrid}];
>> ups = Table[(us[[i]] + us[[i - 1]])/2, {i, 2, ngrid}];
>> ums = Table[(us[[i]] - us[[i - 1]]), {i, 2, ngrid}];
>> Etus = Table[rrms[[i]]*Exp[-ups[[i]]], {i, 1, ngrid - 1}];
>> (*Etu2s=Table[Exp[-ups[[i]]/2],{i,1,ngrid-1}];*)
>>
>> SqEts = Table[
>> rrpms[[i]]*sqrrs[[i]]*Exp[-ups[[i]]/2]*acubed*rba, {i, 1,
>> ngrid - 1}];
>> ElemEIEI = Table[N[SqEts[[i]]/4, Precis], {i, ngrid - 1}];
>> ElemOIOI = Table[N[-Etus[[i]]/2, Precis], {i, ngrid - 1}];
>> ElemOIOI1 =
>> Table[N[yps[[i]]*Etus[[i]]/2, Precis], {i, ngrid - 1}];
>> Es[[ngrid*nvar]] = N[Exp[us[[ngrid]]] - rrs[[ngrid]], Precis];
>> Es[[1]] = Exp[us[[1]]] - rrs[[1]]*ys[[1]];
>> For[i = 1, i <= ngrid - 1, i++,
>> Es[[nvar*i]] = N[yms[[i]] + Yds[[i]] - SqEts[[i]], Precis];
>> Es[[nvar*i + 1]] = N[ums[[i]] - yps[[i]]*Etus[[i]], Precis];
>> ];
>> (* Table of rules used to create the Sms matrix*)
>>
>> MITime = First[
>> Timing[
>> DataSAP = Join[
>> Table[{nvar*i, nvar*(i - 1) + 1} -> N[-1., Precis], {i,
>> ngrid - 1}],
>> Table[{nvar*i, nvar*(i - 1) + 2} -> ElemEIEI[[i]], {i,
>> ngrid - 1}],
>> Table[{nvar*i, nvar*(i - 1) + 3} -> N[1., Precis], {i,
>> ngrid - 1}],
>> Table[{nvar*i, nvar*(i - 1) + 4} -> ElemEIEI[[i]], {i,
>> ngrid - 1}],
>> Table[{nvar*i + 1, nvar*(i - 1) + 1} -> ElemOIOI[[i]], {i,
>> ngrid - 1}],
>> Table[{nvar*i + 1, nvar*(i - 1) + 2} ->
>> ElemOIOI1[[i]] - 1., {i, ngrid - 1}],
>> Table[{nvar*i + 1, nvar*(i - 1) + 3} -> ElemOIOI[[i]], {i,
>> ngrid - 1}],
>> Table[{nvar*i + 1, nvar*(i - 1) + 4} ->
>> ElemOIOI1[[i]] + 1., {i, ngrid - 1}]]
>> ]
>> ];
>> DataSA = Prepend[DataSAP, {1, 2} -> N[Exp[us[[1]]], Precis]];
>> DataSA =
>> Prepend[DataSA, {nvg, nvg} -> N[Exp[us[[ngrid]]], Precis]];
>> DataSA = Prepend[DataSA, {1, 1} -> N[-rrs[[1]], Precis]];
>> Sms = SparseArray[DataSA];
>> ]
>> ];
>>
>> Best regards
>> Alexander
>
>>From a quick look at the code, I would suggest trying the following:
>
> 1. Avoid "growing" the DataSA list using Prepend: this is in general a
> bad way to do it. It looks like you could just bring those last couple
> of operations inside the Join.
>
> 2. Try using Compile: this is useful for cases where you are doing
> many simple operations.
>
> 3. (Possibly the most important but requires a bit more thought): it
> helps a lot if you vectorize your code. That is, instead of something
> like (the following is a trivial example):
>
> x = Table[y[[i]] + z[[i]], {i, n}]
>
> use
>
> x = y + z
>
> Depending on how many elements of the arrays you are accessing, you
> may need to use functions like Take, Drop, Most, Rest, Cases, Select,
> etc.
>
> If you can formulate your calculation in vector form it is likely to
> be close to optimal since Mathematica's built-in list operations are
> highly optimized.
>
Adding to those suggestions, we never got to see the original data that
this code operates on. If at all possible, arrays should be of just one
type - e.g. Real - and if this is appropriate, it might help to apply N
to these arrays to make sure this is so. This will be particularly
relevant if you are able to follow Pfalloon's suggestion to vectorise
your code.
Unfortunately, optimising code is a fairly tricky process, because it is
all too easy to optimise the wrong part of the code - so even though you
sped it up, it only ever accounted for 1% of the total run time, and you
don't see any improvement...
David Bailey
http://www.dbaileyconsultancy.co.uk