caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Bug] Different behavior bytecode/nativecode
@ 2005-02-27  0:13 Christophe TROESTLER
  2005-02-27  2:32 ` [Caml-list] " Kurt Welgehausen
  2005-02-27  4:44 ` Jon Harrop
  0 siblings, 2 replies; 5+ messages in thread
From: Christophe TROESTLER @ 2005-02-27  0:13 UTC (permalink / raw)
  To: O'Caml Mailing List; +Cc: caml-bugs

[-- Attachment #1: Type: Text/Plain, Size: 400 bytes --]

Hi,

When I compile the attached program to bytecode, I get the output
"0.000000 -1.000000 -> 1" (which is correct) but when I compile to
native code the result is "0.000000 -1.000000 -> 0".

The error stops when I substitute "invw" in "let cr = 300. *. invw
-. 1.5" by its definition (i.e. if I write
"let cr = 300. *. (2. /. float w) -. 1.5").

Curious to know what is the problem.

Cheers,
ChriS


[-- Attachment #2: mandelbrot.ml --]
[-- Type: Text/Plain, Size: 484 bytes --]

let niter = 50
let limit = 2.

let limit2 = limit *. limit

let add_bit0 cr ci byte =
  let rec loop i zr zi =
    if zr *. zr +. zi *. zi > limit2 then (byte lsl 1) lor 0x00
    else if i > niter then (byte lsl 1) lor 0x01
    else loop (i + 1) (zr *. zr -. zi *. zi +. cr) (2. *. zr *. zi +. ci) in
  loop 1 0. 0.

let () =
  let w = 400 in
  let invw = 2. /. float w in
  let ci = -1. in
  let cr = 300. *. invw -. 1.5 in
  Printf.printf "%f %f -> %i\n" cr ci (add_bit0 cr ci 0);


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] [Bug] Different behavior bytecode/nativecode
  2005-02-27  0:13 [Bug] Different behavior bytecode/nativecode Christophe TROESTLER
@ 2005-02-27  2:32 ` Kurt Welgehausen
  2005-02-27  4:44 ` Jon Harrop
  1 sibling, 0 replies; 5+ messages in thread
From: Kurt Welgehausen @ 2005-02-27  2:32 UTC (permalink / raw)
  To: caml-list

The problem is in the calculation of cr: it's not really 0.0
in the native code.  I can't tell you why.

let () =
  let w = 400 in
  let invw = 2. /. float w in
  let ci = -1. in
  let cr = 300. *. invw -. 1.5 in
  Printf.printf "%.19f %f -> %i\n" cr ci (add_bit0 cr ci 0);
  print_endline ("invw->"^(Int64.to_string (Int64.bits_of_float invw)));
  print_endline ("cr->"^(Int64.to_string (Int64.bits_of_float cr)));
  print_endline ("ci->"^(Int64.to_string (Int64.bits_of_float ci)))

**kaw<~/ocaml>$ ./mandelbrot
0.0000000000000000000 -1.000000 -> 1
invw->4572414629676717179
cr->0
ci->-4616189618054758400
**kaw<~/ocaml>$ ./mandelbrot.opt 
0.0000000000000000312 -1.000000 -> 0
invw->4572414629676717179
cr->4360047389248061440
ci->-4616189618054758400


Regards


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] [Bug] Different behavior bytecode/nativecode
  2005-02-27  0:13 [Bug] Different behavior bytecode/nativecode Christophe TROESTLER
  2005-02-27  2:32 ` [Caml-list] " Kurt Welgehausen
@ 2005-02-27  4:44 ` Jon Harrop
  2005-02-27 10:13   ` Christophe TROESTLER
  1 sibling, 1 reply; 5+ messages in thread
From: Jon Harrop @ 2005-02-27  4:44 UTC (permalink / raw)
  To: caml-list

On Sunday 27 February 2005 00:13, Christophe TROESTLER wrote:
> When I compile the attached program to bytecode, I get the output
> "0.000000 -1.000000 -> 1" (which is correct) but when I compile to
> native code the result is "0.000000 -1.000000 -> 0".
>
> The error stops when I substitute "invw" in "let cr = 300. *. invw
> -. 1.5" by its definition (i.e. if I write
> "let cr = 300. *. (2. /. float w) -. 1.5").
>
> Curious to know what is the problem.

The problem is the conflict of interests between having ocamlc and ocamlopt 
behave identically, and having ocamlopt-compiled code achieve good 
performance. In floating-point code, ocamlopt can sometimes generate slightly 
different results from ocamlc.

Specifically, your code is numerically unstable at the specified values and 
ocamlopt is generating x86 code which is partly performed in 80-bit registers 
(300. *. invw -. 1.5) and partly stored in 64-bit memory locations (2. /. 
float w) whereas ocamlc is storing everything in 64-bit memory locations. 
This leads ocamlc to a result of exactly zero and ocamlopt to a result 
slightly above zero (cr=0.00000000000000003). The rest of the code is then 
numerically unstable with respect to this result.

Inlining the definition of "invw" simply causes the ocamlopt-compiled 
program's computation to be performed entirely at 80-bits, giving the desired 
result of precisely zero:

$ cat >a.ml
let x = 2. /. 400.;;
Printf.printf "%.30f\n" (300. *. x -. 1.5);;
Printf.printf "%.30f\n" (300. *. (2. /. 400.) -. 1.5);;
$ ocamlc a.ml -o a
$ ./a
0.000000000000000000000000000000
0.000000000000000000000000000000
$ ocamlopt a.ml -o a
$ ./a
0.000000000000000031225022567583
0.000000000000000000000000000000

This is described in chapter 4 of "Objective CAML for Scientists":

  http://www.ffconsultancy.com/products/ocaml_for_scientists/

See also "Re: bug in floating point implementation ?" by Xavier Leroy:

  http://caml.inria.fr/caml-list/1147.html

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://ffconsultancy.com


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] [Bug] Different behavior bytecode/nativecode
  2005-02-27  4:44 ` Jon Harrop
@ 2005-02-27 10:13   ` Christophe TROESTLER
  2005-02-27 11:10     ` Jon Harrop
  0 siblings, 1 reply; 5+ messages in thread
From: Christophe TROESTLER @ 2005-02-27 10:13 UTC (permalink / raw)
  To: jon; +Cc: caml-list

On Sun, 27 Feb 2005, Jon Harrop <jon@jdh30.plus.com> wrote:
> 
> The problem is the conflict of interests between having ocamlc and
> ocamlopt behave identically, and having ocamlopt-compiled code
> achieve good performance. In floating-point code, ocamlopt can
> sometimes generate slightly different results from ocamlc.
>   http://caml.inria.fr/caml-list/1147.html

Thanks for the pointer.

>  Specifically, your code is numerically unstable

Yes, I know about this but was blind-sighted by the different results
of the two compilers... :(   (I checked the values of "cr" where
identical but not with enough precision...)

> ocamlopt is generating x86 code which is partly performed in 80-bit
> registers and partly stored in 64-bit memory locations

Are there general rules about this: does a "let" necessarily put the
result into 64-bit memory (as an assignment in C does) or is it more
complicated (e.g. due to inlining)?

Thanks for quickly finding my mistake!

Regards,
ChriS


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] [Bug] Different behavior bytecode/nativecode
  2005-02-27 10:13   ` Christophe TROESTLER
@ 2005-02-27 11:10     ` Jon Harrop
  0 siblings, 0 replies; 5+ messages in thread
From: Jon Harrop @ 2005-02-27 11:10 UTC (permalink / raw)
  To: caml-list

On Sunday 27 February 2005 10:13, Christophe TROESTLER wrote:
> > ocamlopt is generating x86 code which is partly performed in 80-bit
> > registers and partly stored in 64-bit memory locations
>
> Are there general rules about this: does a "let" necessarily put the
> result into 64-bit memory (as an assignment in C does) or is it more
> complicated (e.g. due to inlining)?

My guess is that your guess is roughly right. I don't think ocamlopt does much 
inlining so you're probably fairly safe. For a detailed and accurate answer 
you'd better ask Xavier. You'd better be quick though, or skaller will reply 
and poison your mind. ;-)

> Thanks for quickly finding my mistake!

Any excuse for a free advert. :-)

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://ffconsultancy.com


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-02-27 11:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-02-27  0:13 [Bug] Different behavior bytecode/nativecode Christophe TROESTLER
2005-02-27  2:32 ` [Caml-list] " Kurt Welgehausen
2005-02-27  4:44 ` Jon Harrop
2005-02-27 10:13   ` Christophe TROESTLER
2005-02-27 11:10     ` Jon Harrop

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).