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.