Re: Re: Question on Compile[]
- To: mathgroup at smc.vnet.net
- Subject: [mg49794] Re: [mg49786] Re: [mg49747] Question on Compile[]
- From: DrBob <drbob at bigfoot.com>
- Date: Sun, 1 Aug 2004 04:09:57 -0400 (EDT)
- References: <200407301002.GAA26336@smc.vnet.net> <200407310714.DAA12055@smc.vnet.net>
- Reply-to: drbob at bigfoot.com
- Sender: owner-wri-mathgroup at wolfram.com
I think Fold is the way to go, here. mukasa[cashFlow_,rate_]:=Module[{nvec=Range[Length[cashFlow]]}, Total[cashFlow/(1.0+rate)^nvec]] andrzej=Compile[{{cashFlow,_Real,1},{rate,_Real}},Module[{ nvec=Range[Length[cashFlow]]},Total[cashFlow/(1.0+rate)^nvec]]]; treat[cc_List,r_]:=Block[{z=1/(1+r)}, z Fold[#1 z+#2&,0,Reverse@cc] ] cashFlow[n_]:=Table[Random[],{n}]; cc=cashFlow[100000]; r=0.1; Timing@mukasa[cc,r] Timing@andrzej[cc,r] Timing@treat[cc,r] {1.484 Second,3.44135} \!\(\* RowBox[{\(CompiledFunction::" cfn"\), \(\(:\)\(\ \)\), "\<\"Numerical error encountered at instruction \\!\\(13\\); proceeding with uncompiled evaluation. \\!\\(\\*ButtonBox[\\\"Moreâ?¦\\\", \ ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, \ ButtonData:>\\\"CompiledFunction::cfn\\\"]\\)\"\>"}]\) {1.547 Second,3.44135} {0.031 Second,3.44135} Bobby On Sat, 31 Jul 2004 03:14:05 -0400 (EDT), Andrzej Kozlowski <akoz at mimuw.edu.pl> wrote: > On 30 Jul 2004, at 12:02, Mark Coleman wrote: > >> >> Greetings, >> >> I am doing some research in finance, translating some visual basic code >> into Mathematica, and attempting to optimize it. Most of this is quite >> straightforward, and by Compiling[] functions, execution is quite fast. >> I did run into an instance where the compilied code ran a bit slower >> than the uncompiled code. I am sure this has something to do with some >> additional work that Mathematica is doing internally to expand the >> expression I >> am using, but I was hoping someone on the list could help me understand >> and if possible fix, this behavior. >> >> Specifically I am calculating a standard discounted cash flow. The >> computation is quite simple, Let >> >> cashFlow be a list of real numbers of length n and let nvec=Range[n], >> then the discounted cash flow is the sum over i=1,n of >> >> cashFlow(i)/(1+r)^i >> >> where r is a real number with 0 < r < 1. >> >> The final Mathematica code is: >> >> >> Clear[dcf]; >> dcf[cashFlow_, rate_] := Module[{nvec = Range[Length[cashFlow]]}, >> Total[cashFlow/(1.0 + rate)^nvec] >> ] >> >> >> On my 800 Mhz Powerbook G4, 5000 trials of this takes 3.72 seconds, >> while the compiled version takes 4.2 seconds. >> >> Any ideas how I can speed this up, to get the usual gains one typically >> sees in compiled code? >> >> Thanks, >> >> -Mark >> >> > > Here is what I see on my machine (also a Mac PowerBook): > > We compare two functions: > > dcf[cashFlow_, rate_] := Module[{nvec = Range[Length[cashFlow]]}, > Total[cashFlow/(1.0 + rate)^nvec] > ] > > > dcf1 = Compile[{{cashFlow, _Real, 1}, {rate, _Real}}, Module[{nvec = > Range[ > Length[cashFlow]]}, > Total[cashFlow/(1.0 + rate)^nvec] > ]] > > Lets also define > > cashFlow[n_]:=Table[Random[],{n}]; > > and lets take > r=0.1; > > Now try > > cc=cashFlow[5000]; > > > dcf[cc,r]//Timing > {0.01 Second,5.65194} > > > dcf1[cc,r]//Timing > {0. Second,5.65194} > > As expected the compiled code is faster. The problem occurs only when > we take a larger n > > In[39]:= > cc=cashFlow[8000]; > > > dcf[cc,r]//Timing > > > {0.15 Second,4.39072} > > > dcf1[cc,r]//Timing > > > "Numerical error encountered at > instruction 1; proceeding with uncompiled evaluation. > > {0.19 Second,4.39072} > > So it is not the case here that the compiled code is slower, rather an > error occurred and a non-compiled version of the function was used. I > think the reason why it fails is that in the body of your function you > have numbers of the form > > c/(rate + 1.)^v > > and when v becomes very large 1/(rate + 1.)^v becomes smaller than > $MinMachineNumber . Since Compile can only work with numerical > quantities that satisfy the usual restriction on machine arithmetic the > compiled function cannot be used and Mathematica switches to compiled > code. Having considered this only briefly I can't yet see as yet any > very satisfactory remedy. The only one I can think of is based on > breaking your function into a linear combination of functions, each of > which is compiled separately in such a way that no numbers smaller than > $MinMachineNumber occur during the computation. Unfortunately the > splitting will have to depend on the length of cashFlow, and it may be > tricky to write such a function that would avoid above difficulty for > all n. > > All this assumes that the problem you have encountered is the same one > I have been discussing. That is not quite obvious from your posting > since you do not mention getting any messages about "proceeding with > uncompiled evaluation". It may be that there is something I have > misunderstood. > > > Andrzej Kozlowski > Chiba, Japan > http://www.mimuw.edu.pl/~akoz/ > > > -- DrBob at bigfoot.com www.eclecticdreams.net