[Haskell-cafe] announce: Glome.hs raytracer

Jim Snow jsnow at cs.pdx.edu
Wed Mar 26 17:33:20 EDT 2008

I have recently posted a haskell port of my ocaml raytracer, Glome:


It supports spheres and triangles as base primitives, and is able to 
parse files in the NFF format used by the standard procedural database 
(http://tog.acm.org/resources/SPD/).  It uses a bounding interval 
heirarchy acceleration structure, so it can render fairly complicated 
scenes in a reasonable amount of time.  Shadows and reflections are 
supported, but not specular highlights or refraction.

It's still slower than the ocaml version, but at least they're in the 
same ballpark (and a good part of that difference may be inefficiencies 
in my BIH traversal).  I would welcome any advice on making it go faster 
or use less memory.

I compile the program with "ghc Glome.hs --make -fasm -O2 -threaded 
-fglasgow-exts -funbox-strict-fields -fbang-patterns -fexcess-precision 
-optc-ffast-math -optc-O2 -optc-mfpmath=sse -optc-msse2".  (I assume the 
-optc options don't do anything unless you compile via C.)

Here are some of my current concerns:

-Multi-core parallelism is working, but not as well as I'd expect: I get 
about a 25% reduction in runtime on two cores rather than 50%.  I split 
the default screen size of 512x512 into 16 blocks, and run "parMap" on 
those blocks with a function that turns the screen coordinates of that 
block into a list of (x,y,r,g,b) tuples that get drawn as pixels to the 
screen through OpenGL by the original thread.

-Memory consumption is atrocious: 146 megs to render a scene that's a 
33k ascii file.  Where does it all go?  A heap profile reports the max 
heap size at a rather more reasonable 500k or so.  (My architecture is 
64 bit ubuntu on a dual-core amd.)

-Collecting rendering stats is not easy without global variables.  It 
occurs to me that it would be neat if there were some sort of write-only 
global variables that can be incremented by pure code but can only be 
read from within monadic code; that would be sufficient to ensure that 
the pure code wasn't affected by the values.  The sorts of things I'm 
looking for are the number of calls to "trace" per image, the number of 
BIH branches traversed and ray/triangle and ray/sphere intersections per 
pixel.   (Disclaimer: I don't really fully understand monads, so I may 
be oblivious to an obvious solution.)

-Is there a fast way to cast between Float and Double?  I'm using Float 
currently, and the only reason is because that's what the OpenGL api 
expects.  I'd like to be able to use either representation, but the only 
way to cast that I've found so far is "float_conv x = 
fromRational(toRational x)", which is too slow.


More information about the Haskell-Cafe mailing list