
Do you have an example of a mutable state/ IO bound application, like, hmm, a window manager or a revision control system or a file system...? If you're looking for a challenge, how about this one (there used to be lots of Haskellers into this game, any of you still around?-): http://computer-go.org/pipermail/computer-go/2008-October/016680.html Interestingly, I did this a while ago. Here's my results:
$ ./Bench 1 100000 b: 14840, w: 17143 mercy: 67982 elapsed time: 3.42s playouts/sec: 29208
so, nearly 30k/sec random playouts on 9x9. That's using a hack that stops the game when the score is heavily in favour of one player, it drops to around 20k/sec with that turned off.
Nice!-) 20k playouts/sec (without the early cutoffs) is the rough number usually mentioned for these light playouts, reachable even in Java. My own Haskell code for that was a factor of 5 slower:-(
Not bad, but probably I'd guess an order of magnitude worse than you can do in tightly-coded C.
Yes, a few people have reported higher rates, but most hobby coders seem happy with 20k/sec - after that, it seems more interesting to move towards heavy playouts and combinations with tree-based search instead of light playouts with simple statistics alone. But if you don't get at least those 20k/sec, it is difficult to run the number of experiments needed to test presumed improvements in playing strength.
The Haskell implementation isn't nice, as you predicted.
What is really annoying for me is that I'm no longer used to this low-level style of coding, so every time I add something, performance goes down, and I have to work to get it back (I modified my playout code to match that reference bot specification - my bot does get the expected 50% wins against jrefbot, but is now a factor of 8 slower (still using only half the memory, though)). Not to mention that I'm throwing away many of the advantages of Haskell. That is one reason why I mentioned this challenge.
Also the code is derived from some non-free internal MS code, so unfortunately I can't share it (but I could perhaps extract the free bits if anyone is really interested).
Interesting, can you tell what kind of code those internal bits are? Of course, the fun is implementing it oneself, but it is very useful to have reference points, such as the refbot spec, or the Java implementation to play against. Your Haskell reference point will spur me to have another look at my bot's performance!-) The Go programming folks have a lot of useful infrastructure, btw, including a server just for bot-vs-bot competition: http://cgos.boardspace.net/ Not to mention monthly tournaments, competions, etc.
It does parallelise too, of course:
$ ./Bench 8 100000 +RTS -N8 b: 14872, w: 17488 mercy: 67584 elapsed time: 1.00s playouts/sec: 99908
though still room for improvement there.
That is the other reason why I mentioned this challenge: the specs people use for their competition bots are interestingly parallel. One example, this year's Computer Go Olympiad results: http://www.grappa.univ-lille3.fr/icga/tournament.php?id=181 Many Faces of Go, winner, currently maxes out at 32 cores, a limitation its author would like to remove (he's working with the Microsoft HPC group, btw). For the exhibition game against a pro that made the news this year, MoGo used a cluster of 800 cores: http://www.mail-archive.com/computer-go@computer-go.org/msg08692.html http://www.mail-archive.com/computer-go@computer-go.org/msg08710.html Of course, the simple reference bot implementations are a far cry from MoGo or ManyFaces, but I thought this would be an interesting non-trivial-but-doable challenge for Haskell performance and parallelism fans, especially since there are still many people interested in Go here;-) Claus