Finite Improbability

Just programming and math, no spontaneously jumping undergarments

Archive for the 'raytracing' Category

Experience writing a ray tracer in Haskell

I promised I would give a bit more in the way of details on the ray tracer. Here they are.

During the last three weeks of the term we were directed to come up with a “term project” for the functional programming course. [1] We needed to come up with something that was interesting and exercised the features we’d been learning about all term. I’ve wanted to write a ray tracer for a while now, so I picked that. The assignment, as I gave it to myself, was to write a minimal but complete ray tracer and report on the experience of profiling and parallelizing it.

The ray tracer itself took around 30 hours of work. Partially this was me struggling with the language, partially me struggling with the topic, and partially me being picky and/or making and fixing bad design decision. When I turned it in it would only do spheres in flat colors and reflection (or a combination) with specular and diffuse lighting. I’ve been working on transparency and diffraction, but that code isn’t really worth showing off yet. I’ll eventually do some more complicated shapes and may explore more interesting materials.

Writing a ray tracer in Haskell was a … luxurious experience. The heart of a ray tracer is almost entirely math, and Haskell represents that very well. The only real difference between my Haskell code and the math behind it was some additional let bindings I introduced while profiling. I enjoyed being able to avoid unnecessary computations implicitly through laziness, instead of explicitly through conditionals, as I would have needed to do in other languages.

I originally planned to spend a few hours working on parallelization. I started playing around with it for fun while I was waking up with coffee one morning. Half an hour and 53 characters later I had around a 40% speedup on two cores. In this, Haskell kind of ruined the project for me. It was too easy to introduce parallelization into the program and have it just work. A very helpful co-worker ran some benchmarks for me on a few systems. Here’s the performance chart.

Performance chart

These results are rather informal, but you can see the impressive increases from parallel execution. I’m not entirely sure what is going on at the eight core mark, but I think it has something to do with an issue with (GHC only?) multicore support on Linux.

If you’d like to point and laugh at my code, you can find it here. I compile it on ghc with “ghc -O -threaded -o ray –make Main.lhs”. Comments are very welcome.

[1] Taught by Mark Jones (the initial author of Hugs) and Tim Sheard (who is just FP brilliant) amazing class.

7 comments