MathGroup Archive 2003

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

Search the Archive

RE: Re: Compile

  • To: mathgroup at smc.vnet.net
  • Subject: [mg45114] RE: [mg45032] Re: Compile
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
  • Date: Wed, 17 Dec 2003 07:54:31 -0500 (EST)
  • Sender: owner-wri-mathgroup at wolfram.com

>-----Original Message-----
>From: Maxim [mailto:dontsendhere@.]
To: mathgroup at smc.vnet.net
>Sent: Saturday, December 13, 2003 12:07 PM
>To: mathgroup at smc.vnet.net
>Subject: [mg45114] [mg45032] Re: Compile
>
>
>
>"Wolf, Hartmut" wrote:
>
>> >-----Original Message-----
>> >From: Maxim [mailto:dontsendhere@.]
To: mathgroup at smc.vnet.net
>To: mathgroup at smc.vnet.net
>> >Sent: Wednesday, December 10, 2003 10:02 AM
>> >To: mathgroup at smc.vnet.net
>> >Subject: [mg45114] [mg45032]  Compile
>> >
>> >
>> >Consider
>> >
>> >In[1]:=
>> >Compile[{},
>> >  Module[{x=0},
>> >    While[
>> >      x++;
>> >      EvenQ[x]
>> >    ];
>> >    x
>> >  ]
>> >][]
>> >
>> >Out[1]=
>> >3
>> >
>> >incorrect. The more I think about this wonderful sentence 
>from Compile
>> >reference -- "The number of times and the order in which objects are
>> >evaluated by Compile may be different from ordinary
>> >Mathematica code" --
>> >the less I understand it. It can mean that if compiled 
>evaluation fails
>> >at some point, Mathematica stops and starts over with the
>> >ordinary code.
>> >But equally well it can be interpreted to mean that Compile 
>may ignore
>> >all the rules of the standard evaluator, including 
>operators precedence
>> >order.
>> >
>> >Of course, in a sense Compile is still in the development stage; for
>> >instance, I don't like the fact that Do[0,{i,1},{j,i,1}] cannot be
>> >compiled because of i in the second iterator, but in this case
>> >Mathematica just gives a message, reverts to uncompiled
>> >evaluation and I
>> >can see what is going on, while if an expression is compiled and
>> >evaluated differently from uncompiled version, I'm at a 
>loss what went
>> >wrong.
>> >
>> >Actually restarting the evaluation can be quite confusing too,
>> >since you
>> >can't tell at which point Mathematica begins the re-evaluation using
>> >uncompiled code, so if the code has side effects then the result is
>> >unpredictable, as in the example below:
>> >
>> >In[1]:=
>> >Module[{L={}},
>> >  Compile[{},
>> >    AppendTo[L,{1}];
>> >    AppendTo[L,{2}];
>> >    Append[L,{3}];
>> >    AppendTo[L,{3}];
>> >    L
>> >  ][]
>> >]
>> >
>> >Compile::cpts: The result after evaluating Insert[L$11, {3}, -1]
>> >     should be a tensor. Non-tensor lists are not supported at present;
>> >     evaluation will proceed with the uncompiled function.
>> >
>> >CompiledFunction::cfse: Compiled expression {{1}, {2}} should be a
>> >machine-size real number.
>> >
>> >CompiledFunction::cfex:
>> >   External evaluation error at instruction 4; proceeding with
>> >   uncompiled evaluation.
>> >
>> >Out[1]= {{1}, {2}, {1}, {2}, {3}}
>> >
>> >Maxim Rytin
>> >
>> >m.r at prontomail.com
>> >
>>
>> Compile translates a subset of Mathematica into intermediate code for a
virtual
>> machine which definitely is different from the Mathematica Interpreter,
such
>> unavoidably different results will come up. This is not conceiled by WRI.
>> Instead, run-time will shorten for problems suitable to compilation.
>>
>> Such code to be Compiled has, in a sense, to be regarded as a different
>> language: the syntax is not quite the same, nor the semantics. So code
which
>> is interpreted, has yet to be debugged for Compile (which, for shure,
often
>> is not quite such easy!). And after it compiles, not, not to be
forgotten:
>> checked for correctness (in the Range of intented application)! You just
>> can't leave that out, as you cannot for C, Fortran, ..., whatever, and no
>> one would complain.
>>
>> If I do that with your code, I get:
>>
>> In[5]:=
>> Compile[{}, Module[{x = 0}, While[x++;
>>         EvenQ[x],];
>>       x]][]
>>
>> Out[5]= 1
>>
>> and
>>
>> In[26]:=
>> Module[{Llama = {}}, Compile[{{L, _Integer, 2}}, AppendTo[L, {1}];
>>       AppendTo[L, {2}];
>>       Append[L, {3}];
>>       AppendTo[L, {3}];
>>       L][Unevaluated[Llama]]]
>>
>> >From In[26]:=
>> CompiledFunction::"cfta": "Argument \!\(Llama$27\) at position \!\(1\)
should \
>> be a rank \!\(2\) tensor of \!\(\"machine-size integer\"\)s."
>>
>> Out[26]= {{1}, {2}, {3}}
>>
>> Both results are correct, although, the second example is far off the
>> "specification" of Compile!
>>
>> --
>> Hartmut Wolf
>
> "run-time will shorten"? As in an old joke, "allows you to get incorrect
>results faster"? (Incorrect in the sense of the uncompiled While semantics,
of
>course). ...

Well, I had warned you off: the uncompiled semantics is not identical to the
compiled semantics.  But if you stick close to the procedural metaphor
("basic syntax, more or less like C"), you will minimize surprises. Some
time ago, me too, ran into this. But we shouldn't do this twice!


> ...Actually if you do run some tests, you will see that 
>one-argument While
>can take more time compiled than uncompiled:
>
>In[1]:=
>Module[{cnt},
>  Do[cnt = 0; While[cnt++; cnt < 1], {10^5}]; 0
>  ] // Timing
>
>Out[1]=
>{1.813 Second, 0}
>
>In[2]:=
>Compile[{},
>  Module[{cnt},
>    Do[cnt = 0; While[cnt++; cnt < 1], {10^5}]; 0
>]][] // Timing
>
>Out[2]=
>{10.015 Second, 0}
>

Well, the timings on my machine are:

In[1]:=
Module[{cnt}, Do[cnt = 0; While[cnt++; cnt < 1], {10^5}]; 0] // Timing

Out[1]=
{2.354 Second, 0}
In[2]:=
Compile[{}, 
      Module[{cnt}, Do[cnt = 0; While[cnt++; cnt < 1], {10^5}]; 
        0]][] // Timing

Out[2]=
{11.336 Second, 0}
In[3]:=
Compile[{}, 
      Module[{cnt}, Do[cnt = 0; While[cnt++; cnt < 1,], {10^5}]; 
        0]][] // Timing

Out[3]=
{0.13 Second, 0}


So my compiled version is roughly faster than yours by a factor of 100, and
by a factor of 20 to the uncompiled version.

Some time ago I had to learn that the one element While doesn't compile
correctly. (Or said differently: is not part of the admissible syntax for
Compile). That registered, ok, and a basic understanding of Compile (as
written in the book) should keep us from getting stuck: just do what you
would do in any other case, at any other place. Transfer your code to the
most simple (minded) form, check and debug. That means, look at all
information you have, or may get easily, and compare results with uncompiled
simple code. In effect that's it!



>What is really important is this: suppose I give you two 
>examples and ask you how they'll work:
>
>Compile[{},
>    Module[{cnt = 0},
>      While[cnt++; cnt < 1]; cnt
>      ]
>    ][]
>
>and
>
>Compile[{},
>    Module[{cnt = -1},
>      While[cnt++; cnt < 1]; cnt
>      ]
>    ][]
>
>It's impossible to answer without running both examples and learning about
this
>quirk in the While evaluation. 

Well, I would refuse to guess, as the syntax isn't correct (for Compile, not
for the Mathematica interpreter).

> ...I don't know what you mean in your message by
>"debugged for Compile" and "checked for correctness", 

More or less that above, or have additional looks into the compiled result,
look:

In[15]:= cwhile1 = Compile[{}, Module[{cnt = 0}, While[cnt++; cnt < 1];
cnt]];

In[12]:= cwhile1[]
Out[12]= 2

In[16]:= cwhile1[[-1]][]
Out[16]= 1

Ok, a bug!
Now, have a deeper look:

In[18]:= cwhile1 // InputForm
Out[18]//InputForm=
CompiledFunction[{}, {{2, 0, 0}}, {1, 4, 0, 0, 0}, 
 {{1, 4}, {4, 0, 0}, {9, 0, 1}, {4, 1, 2}, 
  {24, 0, 2, 3}, {9, 3, 0}, {4, 1, 3}, {50, 0, 3, 0}, 
  {21, Function[{}, While[cnt++; cnt < 1]], 
   {cnt, 2, 0, 0, Module}, 6, 0, 17}, {2}}, 
 Function[{}, Module[{cnt = 0}, While[cnt++; cnt < 1]; 
    cnt]]]


Do you see how the while loop exits from the interpreted code? I would not
like this, distrust it. More pleasant is this:

In[22]:= cwhile2 = Compile[{}, Module[{cnt = 0}, While[cnt++; cnt < 1,];
cnt]];

In[23]:= cwhile2 // InputForm
Out[23]//InputForm=
CompiledFunction[{}, {{2, 0, 0}}, {1, 4, 0, 0, 0}, 
 {{1, 4}, {4, 0, 0}, {9, 0, 1}, {4, 1, 2}, 
  {24, 0, 2, 3}, {9, 3, 0}, {4, 1, 3}, {50, 0, 3, 0}, 
  {43, 0, 2}, {44, -7}, {2}}, 
 Function[{}, Module[{cnt = 0}, 
   While[cnt++; cnt < 1, Null]; cnt]]]



>                      ...but are you sure that's
>how you're supposed to learn a programming language? "I know that
While[cond]
>will evaluate this way when compiled and While[cond,body] will evaluate
that way
>because I tried it"? Sorry, that's ridiculous.
>
Well, I wouldn't put forward that question (perhaps except when I had to pay
for a teacher).
I'd just like to swiftly find a solution, and go ahead. 

And for that, compiled code is a resource too precious to simply put away.



>Try looking at the bigger picture -- suppose you have to develop a large
>application (and then have to locate such glitches in thousands lines of
code).
>How can you be sure that something else but similar won't come up?
>

By conventional Software Engineering: reduce complexity, find a clear
structure, build from simple parts, debug and check for correctness. Same as
everywhere. And there still is left plenty room for constructive phantasy,
and thus, pure joy!


>As to the second example, I'm saying that in case of side effects result
will be
>unpredictable and you give me an example without side effects. 
>Okay...I guess.
>
>Maxim Rytin
>m.r at prontomail.com
>
>

Maxim, certainly we share the desire for more, and explicit documentation!
Hope to have helped, in a sense.

--
Hartmut


  • Prev by Date: RE: speed-up of a function
  • Next by Date: RE: arXiv style sheet on Mac OSX
  • Previous by thread: Re: Compile
  • Next by thread: Re: Compile