[Haskell-cafe] announce: Glome.hs raytracer

Don Stewart dons at galois.com
Wed Mar 26 17:45:08 EDT 2008

> I have recently posted a haskell port of my ocaml raytracer, Glome:
> http://syn.cs.pdx.edu/~jsnow/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.)

Use a Writer monad to log statistics? Maybe a State monad.
> -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.

I'd try realToFrac, which should be pretty much optimised away.

With doubles, ensure you use -fexcess-precision 

-- Don

More information about the Haskell-Cafe mailing list