Re: Can I do this faster?
- To: mathgroup at smc.vnet.net
- Subject: [mg102998] Re: Can I do this faster?
- From: Szabolcs Horvát <szhorvat at gmail.com>
- Date: Thu, 3 Sep 2009 19:54:14 -0400 (EDT)
- References: <h7o2cd$jtk$1@smc.vnet.net>
On 2009.09.03. 11:30, Andreas wrote: > Rest[FoldList[Times, 1, Transpose[(t = #; 1 + Inner[Times, t, # - 1, > Plus]& /@ list1)& /@ > list2]]] First I'd like to say that it's often much easier (at least for me!) to come up with a solution if you explain what you want to do in plain English instead of just providing a program to speed up. Now I have to convert the program to a form that my brain can handle, then convert it back to program code... Why not avoid the first step if possible? ;-) So, a few things we might notice about this implementation: 1. Inner is used with Times and Plus, so why not replace it with Dot? 2. That nested function (with the assignment to the global t) looks discomforting. I'm not sure how Mathematica's compiler can handle that (Map auto-compiles the function when working on large lists). So let's try to get rid of that also. These might not be the main reson for the slowdown. I am just guessing---predicting Mathematica's performance can be difficult. So, rewrite the inner part of the program first. Instead of Inner we can use Dot, instead of the nested function we can use Outer: list1 = RandomReal[{0, 1}, {1500, 3}]; list2 = RandomReal[ExponentialDistribution[2], {1000, 3}]; In[3]:= Timing[ x = Transpose[(t = #; 1 + Inner[Times, t, # - 1, Plus] & /@ list1) & /@ list2];] Out[3]= {21.656, Null} In[4]:= Timing[y = Outer[1 + #2.(#1 - 1) &, list1, list2, 1];] Out[4]= {10.625, Null} That's a 2x speedup. Are the results equivalent? In[5]:= x == y Out[5]= False We got False, but that's only because of numerical errors (the operations are performed in a different order): In[6]:= Max@Abs[x - y] Out[6]= 8.88178*10^-16 So the result is correct. What else can we do to speed things up? Notice that it is not necessary to subtract/add 1 in the inner function 1 + #2.(#1 - 1) &. This can be done on the input and output instead. So we can get rid of custom functions and use the built-in Dot only: In[7]:= Timing[z = 1 + Outer[Dot, list1 - 1, list2, 1];] Out[7]= {1.25, Null} In[8]:= y == z Out[8]= True Now that's a 17x speedup compared to the implementation we started with. Trying to simplify things will often pay off because it will be easier to see how to rewrite the program to use built-in functions and packed arrays as much as possible. It's also much easier to see what the program does. The FoldList part takes an additional 3 seconds on my machine. I can't help with speeding that up unfortunately. I hope this helps, Szabolcs
- Follow-Ups:
- Re: Re: Can I do this faster?
- From: DrMajorBob <btreat1@austin.rr.com>
- Re: Re: Can I do this faster?
- From: DrMajorBob <btreat1@austin.rr.com>
- Re: Re: Can I do this faster?