Thoughts on Perl and Emacs, technology and writing

Speed comparison: PLT Scheme, Ocaml and C++

One of the problems given to solve in HTDP was to write a program that solved the 8 queens problem, that is, to place 8 queens on a standard chess board so that none of them are attacking each other. I quite enjoyed working through this, and came up with something that used a straight size 64 scheme vector to represent the board which I thought would be reasonably efficient.

First of all, as encouraged by HTDP, there were the functions to manipulate and display the board:

I’ve attached the code at the end along with fairly naive translations into Ocaml and C++.

The surprising thing to me though is that vast differences in speed. The Ocaml runs around 15 times faster than the scheme, and the C++ runs around 20 times faster than the Ocaml. Now, to some people, this might suggest that C++ is much faster than Ocaml which in turn is much faster than PLT Scheme. However, the wealth of information around on the net leads me to believe that this is not true. I therefore conclude that I am not very good at writing efficient scheme or efficient Ocaml.

I can see that there are minor algorithmic differences between the code. In particular, the C++ uses out-of-bound data rather than a Some / None type as in the Ocaml. Additionally, the C++ uses simple machine integers to represent the square types. It is difficult to believe that this accounts for the difference though, in which case, what am I doing wrong?

Share this:

Like this:

Related

15 Responses

Did you compile the Ocaml to native code — that is, did you use “ocamlopt” instead of “ocamlc” or the repl? If you’re using the interpreter, a factor of 15 or 20 relative to C++ sounds about right, actually.

I’d expect a difference of at most 4x for compiled Ocaml versus compiled C++, for floating point or bit bashing code. If your app involves allocating lots of small short-lived objects, then I’d expect Ocaml to be marginally faster than C++.

Richards solution is is clever. However, it only counts the number of solutions, but the three bytes ld, cols, and rd doesn’t contain enough information to print out the board when a solution is found (when cols=all).

> Neel Krishnaswami Says:
> December 22nd, 2006 at 4:54 pm
>
> Did you compile the Ocaml to native code – that is, did you use “ocamlopt” instead of “ocamlc” or the repl? If you’re
> using the interpreter, a factor of 15 or 20 relative to C++ sounds about right, actually.

Yes I did. Here are the commands executed – I took the arguments to the compiler from the shootout
(q.exe is the compiled ocaml, a.exe is the compiled C++).

> Jens Axel Søgaard Says:
> December 22nd, 2006 at 5:19 pm
>
> Inlining a few of the functions speeds things up a bit.
> With minimal changes this can be done as follows:

[snip]

This gave a speed-up of about 20% – define-inline is a nice macro, thanks.

> Jens Axel Søgaard Says:
> December 22nd, 2006 at 5:32 pm
>
> I know the point of the post is to compare the speed of similar approaches in different languages,
> but you can save a *lot* of time by changing the representation of a board.
>
> At the moment add-queen creates a new array each time a new board configuration is visited.
> The representation in
>
> avoids this copying, and is much faster. Try it!

Yes, much faster, you’re right. This gives a similar speed to the C++.

> # Warren Henning Says:
> December 22nd, 2006 at 6:09 pm
>
> Is using all that pattern matching in the OCaml code really necessary?

I’ve no idea, this is my first piece of OCaml. Do you have any suggestions for improvements?

Jon: As I understand it, the point was never to write a fast implementation, but rather to compare the run-time of similar implementation approaches under different languages.
Faster code can be written in any language, but that would make the comparison between languages useless as you’re not comparing similar algorithms.

Mark, my point was that this OCaml implementation goes out of its way to box and check values at run-time. This is necessary in Lisp or Scheme but not in OCaml, Standard ML, Haskell, F#, Scala or any other modern functional programming language.