MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Speeding Up Numerical Matrix Calculations ???

  • To: mathgroup at christensen.cybernetics.net
  • Subject: [mg1124] Re: Speeding Up Numerical Matrix Calculations ???
  • From: wagner at bullwinkle.cs.Colorado.EDU (Dave Wagner)
  • Date: Mon, 15 May 1995 02:41:49 -0400
  • Organization: University of Colorado, Boulder

In article <3ouung$995 at news0.cybernetics.net>,
Paul E Howland  <PEHOWLAND at taz.dra.hmg.gb> wrote:
>My question is quite simple.  Mathematica can be numerically very slow.  
>How can I speed up my numerical calculations involving matrices that 
>consist only of machine size numbers?
>
>It appears that Mathematica handles numerical matrices in much the same
>way as it does symbolic matrices.  Here's a test I did using Mathematica
>V2.2.3 on a 486/33 PC running Windows 3.1. 
>
>In[1]:= F[a_?MatrixQ, b_?MatrixQ, c_?MatrixQ] :=
>	Transpose[a]a + 3 b c + Transpose[c]c
>In[2]:= NF[a_?MatrixQ, b_?MatrixQ, c_?MatrixQ] :=
>	N[Transpose[a]a + 3 b c + Transpose[c]c]
>
>Now generate some machine sized numerical matrices ...
>
>And some symbolic matrices ...
>
>And compare timings.  First compare F[] on both sets of data ...
>
>In[9] := Timing[Do[F[a,b,c], {i,10}]]
>Out[9] = {3.185 Second, Null}
>In[10] := Timing[Do[F[x,y,z], {i,10}]]
>Out[10] = {2.087 Second, Null}
>
>thus the symbolic processing is faster (!).

It certainly appears that ordinary multiplication is not optimized for
machine-precision arguments.  Dot-product, however, is:

In[30]:=
    F2[a_?MatrixQ, b_?MatrixQ, c_?MatrixQ] :=
	    Transpose[a].a + 3 b.c + Transpose[c].c

In[31]:=
    Timing[Do[F2[a,b,c], {i,10}]]
Out[31]=
    {0.583333 Second, Null}

In[32]:=
    Timing[Do[F2[x,y,z], {i,10}]]
Out[32]=
    {6.31667 Second, Null}

(Assuming what you really want to do is a dot-product.)

>It is not possible to use Compile[] on a function that accepts matrices 
>as arguments because Compile[] only accepts _Integer, _Real and _Complex 
>as its data types (and not _List).

You can sometimes get a speedup just by compiling very simple
functions, in this case Times:

In[43]:=
    fasttimes = Compile[{{x, _Real}, {y, _Real}},
	    x * y
    ]
Out[43]=
    CompiledFunction[{x, y}, x y, -CompiledCode-]

In[44]:=
    fasttimes[3., 4.]
Out[44]=
    12.

Now we need a fast way to apply this function pairwise to two matrices.

In[57]:=
    matrixtimes[m1_, m2_] :=
	    MapThread[fasttimes, {m1, m2}, 2]

In[58]:=
    matrixtimes[{{1.,2.},{3.,4.}},{{5.,6.},{7.,8.}}]
Out[58]=
    {{5., 12.}, {21., 32.}}

Here's another version of F that uses matrixtimes rather than Times:

In[59]:=
    F3[a_?MatrixQ, b_?MatrixQ, c_?MatrixQ] :=
	    matrixtimes[Transpose[a],a] +
	    3 matrixtimes[b,c] +
	    matrixtimes[Transpose[c],c]

It works:

In[67]:=
    F[a,b,c] == F3[a,b,c]
Out[67]=
    True

But it's apparently not much faster:

In[12]:=
    Timing[Do[F[a,b,c], {i,10}]]
Out[12]=
    {0.866667 Second, Null}

In[61]:=
    Timing[Do[F3[a,b,c], {i,10}]]
Out[61]=
    {0.75 Second, Null}

However, if the matrices are larger, the overheads of the initial function
call, etc., will not play so large a role in the timings:

In[72]:=
    a2 = Table[Random[], {i,100}, {j,100}];
In[73]:=
    b2 = Table[Random[], {i,100}, {j,100}];
In[74]:=
    c2 = Table[Random[], {i,100}, {j,100}];

In[75]:=
    Timing[F[a2,b2,c2];]
Out[75]=
    {9.5 Second, Null}

In[76]:=
    Timing[F3[a2,b2,c2];]
Out[76]=
    {6.75 Second, Null}

Admittedly, this isn't terrific.  Supposedly the compiler will be
substantially enhanced in the next version of Mma.  Maybe someone
at WRI would care to comment on that?

>It would be nice if Mathematica was written such that
>when N[] was wrapped around simple numerical matrix operations, optimised
>numerical code was invoked. 

N is the function that everyone uses but hardly anyone really understands.
The way N[expr] works is that first, expr is evaluated.  If the result
is a normal expression (i.e., head[arg, arg, arg...]), *then* N looks
for rules of the form N[head[...]] := ... to apply; such rules are called
NValues (big surprise there!)  Finally, N numericalizes every number it
can find in the result.  So you see, since the expression inside the N
in your case evaluates before N can do anything, it's not possible for
"optimised numerical code" to be invoked.  It is necessary for a
separate function to be written, say NTimes.  In fact, this is the
reason that there are functions like NSum, NIntegrate, NRoots, etc:  if
you call N[Integrate[expr, ...]] on an expression that can't be
integrated, first Integrate tries and fails, then N sees that the head
of the result is Integrate and so NIntegrate is called.  It's much
faster if you call NIntegrate in the first place.

"Selected Tutorial Notes", available from WRI.  Buy 'em, you'll be
happy you did.

		Dave Wagner
		Principia Consulting
		(303) 786-8371
		dbwagner at princon.com
		http://www.princon.com/princon



  • Prev by Date: Re: Help: General Protection Fault caused by Mathematica for Windows
  • Next by Date: Dynamic Programming, Any packages or Tips?
  • Previous by thread: Speeding Up Numerical Matrix Calculations ???
  • Next by thread: Re: path