Re: Compiled function changes somehow.
- To: mathgroup at smc.vnet.net
- Subject: [mg78589] Re: [mg78568] Compiled function changes somehow.
- From: Andrzej Kozlowski <akoz at mimuw.edu.pl>
- Date: Thu, 5 Jul 2007 03:56:13 -0400 (EDT)
- References: <200707040940.FAA08568@smc.vnet.net>
On 4 Jul 2007, at 18:40, Nacho wrote:
> Hello.
>
> I have been playing with Compile to accelerate some simple code and I
> have found some differences that I cannot explain.
>
> The standard/compiled code is as follows:
>
> standard[max_] :=
> Table[n/m, {n, 1, max}, {m, 1, max}] // N // Flatten;
>
> compiled =
> Compile[{{max, _Integer}},
> Table[n/m, {n, 1, max}, {m, 1, max}] // N // Flatten];
>
> So I can do the same calculations with both codes:
>
> In[19]:= standardresult = standard[1000]; // Timing
>
> Out[19]= {2.969, Null}
>
> In[20]:= compiledresult = compiled[1000]; // Timing
>
> Out[20]= {0.422, Null}
>
>
> The second is much faster, as expected. But are the results the same?
> Apparently, yes:
>
> In[21]:= standardresult == compiledresult
>
> Out[21]= True
>
> In[22]:= standardresult === compiledresult
>
> Out[22]= True
>
>
> But when I use Union in the lists to count the number of different
> elements, I have this surprise:
>
> Length[Union[standardresult]]
> Length[Union[compiledresult]]
>
> Out[23]= 608383
> Out[24]= 634815
>
> So they are not exactly the same... I think that the correct answer
> comes from the uncompiled version. It is the same if I remove the //N
> so it can be compared symbolically.
>
> Is this behaviour expected? Am I missing something?
>
> Both seem to be Machine Precision, but obviously there are some little
> differences. This happens with V5.2 and V6.0.
>
> Any hint?
>
> Thank you.
>
>
It is easy to see that there are small differences in the numbers
generated:
a = standard[10]; b = compiled[10];
s = Pick[a, a - b, x_ /; x != 0];
t = Pick[b, a - b, x_ /; x != 0];
s - t
{-1.11022*10^-16, -5.55112*10^-17, 2.22045*10^-16, 1.11022*10^-16,
1.11022*10^-16, -2.22045*10^-16, -1.11022*10^-16,
4.44089*10^-16, -2.22045*10^-16, 2.22045*10^-16,
1.11022*10^-16, -1.11022*10^-16, 2.22045*10^-16, 4.44089*10^-16,
2.22045*10^-16, 2.22045*10^-16}
All these numbers are small enoguh to be regarded by Mathematica as
equal by default:
Chop[s - t]
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
(but not if you use Chop[s - t, 10^-18]). So when eventually these
small differences will affect the answer you will get from Length
[Union]. In fact this happens once n exceeds 15:
n = 1; While[n++;
Length[Union[a = standard[n]]] == Length[Union[b = compiled1[n]]],]
n
15
Length[Union[standard[15]]]
143
Length[Union[compiled[15]]]
144
You are right that that the uncompiled code gives somewhat more
accurate answer, if by accurate answer you mean the number of
different fractions that you get in the exact list:
Table[n/m, {n, 1, max}, {m, 1, max}]
In fact this number is given by the function:
F[n_] := 2 (Sum[EulerPhi[i], {i, 1, n}]) - 1
(the proof is a nice exercise in elementary number theory so I won't
disclose it here)
and indeed, we see that
F[15]
143
In your case:
F[1000]
608383
which confirms that the uncompiled version is better. However, there
is no doubt that the uncompiled version will eventually also start
giving "wrong answers" - if be wrong you mean answers different from
the values of the above function F. This, of course, is inevitable if
you use inexact numbers. The fact that the compiled version of your
function gives slightly (measured as relative error) different
answers from the non-compiled one may seem somewhat disconcerting but
it is (almost) certainly not any kind of bug, since machine precision
computation is not really meant or suitable for this type of "exact"
computation.
Andrzej Kozlowski
- References:
- Compiled function changes somehow.
- From: Nacho <ncc1701zzz@gmail.com>
- Compiled function changes somehow.