Re: Timing differences
- To: mathgroup at smc.vnet.net
- Subject: [mg63126] Re: Timing differences
- From: Peter Pein <petsie at dordos.net>
- Date: Thu, 15 Dec 2005 03:06:34 -0500 (EST)
- References: <dnopi7$2hn$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
Trevor Baca schrieb: > The question towards the end asks how there can be a timing difference > of 4 or 5 orders of magnitude with the definition of only a single > extra function. > > If we make a toy type called labelledInteger and overload Plus[ ] to > define addition between labelledIntegers, we might get very > satisfactory results, like this: > > In[1]:= > labelledIntegerQ[li_]:=MatchQ[li,labelledInteger[_Integer,label_String]] > > In[2]:= > labelledInteger/:Plus[l___labelledInteger]:= > labelledInteger[Total[First/@{l}],"total"] > > In[3]:= > t=Flatten[Table[labelledInteger[n,"foo"],{n,1,10}]] > > Out[3]= > {labelledInteger[1,"foo"],labelledInteger[2,"foo"],labelledInteger[3,"foo"], > > labelledInteger[4,"foo"],labelledInteger[5,"foo"],labelledInteger[6,"foo"], > > labelledInteger[7,"foo"],labelledInteger[8,"foo"],labelledInteger[9,"foo"], > labelledInteger[10,"foo"]} > > In[4]:= > Timing[Total[t]] > > Out[4]= > {0.000486 Second,labelledInteger[55,"total"]} > > > Fractions of a second is good. > > But now, if we do the exact same thing (starting a new session with the > kernel) but with the addition of overloading Plus[ ] a second time (to > define addition between a labelledInteger and a normal integer) then we > get MUCH slower results: > > In[1]:= > labelledIntegerQ[li_]:=MatchQ[li,labelledInteger[_Integer,label_String]] > > In[2]:= > labelledInteger/:Plus[l___labelledInteger]:= > labelledInteger[Total[First/@{l}],"total"] > > In[3]:= > labelledInteger/:l_labelledInteger+n_Integer:= > labelledInteger[First[l]+n,Last[l]] > > In[4]:= > labelledInteger[10,"foo"]+7 > > Out[4]= > labelledInteger[17,"foo"] > > In[5]:= > t=Flatten[Table[labelledInteger[n,"foo"],{n,1,15}]] > > Out[5]= > {labelledInteger[1,"foo"],labelledInteger[2,"foo"],labelledInteger[3,"foo"], > > labelledInteger[4,"foo"],labelledInteger[5,"foo"],labelledInteger[6,"foo"], > > labelledInteger[7,"foo"],labelledInteger[8,"foo"],labelledInteger[9,"foo"], > labelledInteger[10,"foo"],labelledInteger[11,"foo"], > labelledInteger[12,"foo"],labelledInteger[13,"foo"], > labelledInteger[14,"foo"],labelledInteger[15,"foo"]} > > In[6]:= > Timing[Total[t]] > > Out[6]= > {16.7988 Second,labelledInteger[120,"total"]} > > 17 seconds is bad. > > What on earth is going on here? One workaround is clear: create a named > function for either or both types of addition and don't overload Plus[ > ] twice this way; but what I really want to know is why the second > definition causes such a dramatic increase in timing. > > Trevor. > Hi Trevor, use labelledInteger /: Plus[l__labelledInteger /; Length[{l}] > 1] := labelledInteger[Plus @@ First /@ {l}, "total"]; With this definition I get Short[(1/Second)*First /@ (tm = Timing[Total[Table[labelledInteger[n, "foo"], {n, #1}]]]& /@ Range[100])] --> {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,<<78>>,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.} Last[tm] --> {0.*Second, labelledInteger[5050, "total"]} I can't explain, why it takes so much time, when defining Plus for labeledInteger-sequences of arbitrary length. But of course length 0 is supeflous and since Plus has attribute OneIdentity (Plus[x]==x --> True), it is sufficient to define the special behaviour for sequences of length two or more. Peter