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