Re: Speed wars: OCaml vs. F#



w_a_x_man@xxxxxxxxx wrote:
OCaml: 5.921 seconds
F#: 2.641 seconds

For this task F# is 2.24 times as fast.

That is quite common for numerical tasks because OCaml's lack of JIT
compilation forces it to use a uniform representation of values in general.

OCaml -----------------------

let runs = 100
let max_iterations = 1000

let iterate ci cr =
let bailout = 4.0 in
let rec loop zi zr i =
if i > max_iterations then
0
else
let temp = zr *. zi and
zr2 = zr *. zr and
zi2 = zi *. zi in
if zi2 +. zr2 > bailout then
i
else
loop (temp +. temp +. ci) (zr2 -. zi2 +. cr) (i + 1)
in
loop 0.0 0.0 1

In this case, your use of a recursive function rather than a loop is
probably leading OCaml to needlessly box and immediately unbox the function
arguments. Using a loop instead should improve performance significantly.

let mandelbrot n =
for y = -39 to 38 do
if 1 = n then print_endline "";
for x = -39 to 38 do
let i = iterate
(float x /. 40.0) (float y /. 40.0 -. 0.5) in
if 1 = n then
print_string ( if 0 = i then "*" else " " );
done
done;;

let start_time = Sys.time () in
for iter = 1 to runs do
mandelbrot iter
done;
print_endline "";
print_float ( Sys.time () -. start_time );
print_endline "";


F# ----------------------------

open System

let runs = 100
let max_iterations = 1000

let iterate ci cr =
let bailout = 4.0 in
let rec loop zi zr i =
if i > max_iterations then
0
else
let temp = zr * zi and
zr2 = zr * zr and
zi2 = zi * zi in
if zi2 + zr2 > bailout then
i
else
loop (temp + temp + ci) (zr2 - zi2 + cr) (i + 1)
in
loop 0.0 0.0 1

On the other hand, what you are really doing is complex-valued arithmetic
and, consequently, it would be interesting to compare the performance of
idiomatic code that uses the complex number representations provided with
OCaml and F#. You will find that F# runs circles around OCaml there (e.g.
FFT over complexes is 5.5x faster in F# than OCaml) because OCaml cannot
support structs efficiently because it lacks JIT compilation (or whole
program optimization like MLton) so it is forced to box all complex
numbers, which is hugely inefficient in numerical routines.

Furthermore, algorithms like this one can benefit enormously from
parallelism on multicore machines. F# makes that easy whereas OCaml makes
it hard or impossible.

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



Relevant Pages

  • Re: Bugs at my web site
    ... > an array bounds violation has occured and breaking if it has isn't ... The only question is for JIT compilers. ... Consider a constant loop, or a loop with the limit equal to the ... The JIT compiler can also test for a try/catch block and only generate ...
    (comp.lang.fortran)
  • Re: LISP vs HASKELL vs PROLOG
    ... the predictably-excellent performance of OCaml but with ... use JIT compilation as Lisp and .NET do, ... OCaml got ... Type system: OCaml's static type system is invaluable but OCaml lacks ...
    (comp.lang.lisp)
  • Re: Collections in .NET (C#)
    ... Note that you run this code as a debug build, which means with most JIT ... result(the result x is loop scoped, so not used outside the loop). ... Below is a converted sample show ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Speed-up for loops
    ... be nice if you could directly code low-level algorithms in it without ... Are you volunteering to write the JIT ... any real code that would need to be put in a for loop is almost certainly ... going to be too complicated for the JIT compiler to benefit greatly. ...
    (comp.lang.python)
  • Re: JVM vs. EXE comaprison
    ... >>> irrelevant because I wouldn't use OCaml byte code for this. ... >>> only use OCaml's bytecode for fast compilations. ... The fact that Java JIT VM's get so close to native program ...
    (comp.lang.java.programmer)