<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>The Development Jungle</title>
	<atom:link href="http://developmentjungle.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://developmentjungle.wordpress.com</link>
	<description>Hacking a path through the complexities of software</description>
	<lastBuildDate>Wed, 13 Jan 2010 08:19:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='developmentjungle.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>The Development Jungle</title>
		<link>http://developmentjungle.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://developmentjungle.wordpress.com/osd.xml" title="The Development Jungle" />
	<atom:link rel='hub' href='http://developmentjungle.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Optimising Mandelbrot</title>
		<link>http://developmentjungle.wordpress.com/2009/11/24/optimising-mandelbrot/</link>
		<comments>http://developmentjungle.wordpress.com/2009/11/24/optimising-mandelbrot/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 22:55:31 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[programming-languages]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[optimisation]]></category>

		<guid isPermaLink="false">http://developmentjungle.wordpress.com/?p=37</guid>
		<description><![CDATA[In my previous post I showed how I created a Mandelbrot fractal renderer in Clojure, however its performance left a lot to be desired. Optimising code is actually a very good way to learn more about a new language as it teaches you what is going on under the hood. In this post, I will [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=developmentjungle.wordpress.com&amp;blog=9851043&amp;post=37&amp;subd=developmentjungle&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://developmentjungle.files.wordpress.com/2009/11/clojure-mandelbrot-set-preview.png?w=700" alt="" title="Clojure Mandelbrot Set"   class="alignright size-full wp-image-15" />In my previous post I showed how I created a <a href="/2009/11/14/rendering-the-mandelbrot-set-in-clojure/">Mandelbrot fractal renderer in Clojure</a>, however its performance left a lot to be desired. Optimising code is actually a very good way to learn more about a new language as it teaches you what is going on under the hood. In this post, I will go through the steps I took to drastically improve the application&#8217;s performance.</p>
<h2>Inspecting the Code</h2>
<p>The first step when optimising code (after <a href="http://c2.com/cgi/wiki?PrematureOptimization"><em>not</em> optimising</a> of course) is to inspect the code&#8217;s logic and find quick fixes to any obvious potential performance areas. The logic of the Mandelbrot code however is fairly easy to reason about as we have built it up from the mathematical formula. Also, looking for obvious performance issues is difficult in a language you are trying to learn, so it&#8217;s time to break out the tools.<br />
<span id="more-37"></span></p>
<h2>Profiling</h2>
<p>First of all, let&#8217;s see how long it takes to render our fractal with the current implementation:</p>
<p><pre class="brush: javafx;">
user=&gt; (time (my-mandelbrot))
&quot;Elapsed time: 29340.692742 msecs&quot;
nil
</pre></p>
<p>Note, I have undone the premature optimisation I made last time and made the rendering single threaded by replacing <code>pmap</code> with <code>map</code>. This is important when profiling as it ensures we can properly determine which parts of the code are taking the longest. On a quad core cpu, I found that using <code>pmap</code> gave only a 2x speed increase which shows there is quite a lot of overhead in Clojure when processing on multiple threads.</p>
<p>Now at this stage, we have no idea what is taking so long so let&#8217;s run the app through a profiler. As Clojure is hosted on the JVM, it allows us to take advantage of many tools that would normally be used for Java applications. I attached the <a href="https://visualvm.dev.java.net/">VisualVM</a> profiling tool (which now comes with Java 6) to my application and then called <code>my-mandelbrot</code> again from the REPL. This is what I got after running for a few minutes:</p>
<p><img class="aligncenter size-full wp-image-55" title="VisualVM profile of render" src="http://developmentjungle.files.wordpress.com/2009/11/profile-render.png?w=700" alt=""   /></p>
<p>What strikes you when digging through a Clojure call tree is just how deep it can go. It can also be difficult to relate the Java method calls we see back to the original Clojure code. Here I have expanded the calls made within the <code>render</code> function. You can see the two main consumers of CPU time are calls to <code>count</code> and <code>vec</code>. This is surprising as if you have a look at the original <code>render</code> function code, there&#8217;s not a call to either the <code>count</code> or <code>vec</code> functions to be seen:</p>
<p><pre class="brush: javafx;">
(defn render [xstart ystart xsize ysize width height max-iters wr]
  (dorun
    (map (fn [pixel]
            (let [[x y] pixel]
              (.setPixel wr x y
                (int-array (coord-colour
                  (get-coord (double x) (double y) xstart ystart xsize ysize width height)
                  max-iters)))))
           (get-pixels width height))))
</pre></p>
<p>In fact, <code>count</code> is called from within the <code>coord-colour</code> function:</p>
<p><pre class="brush: javafx;">
(defn coord-colour
  &quot;Returns a colour for which to draw the given coordinate. If the coordinate
  is within the mandelbrot set, black is returned. Otherwise, a colour within
  a gradient is given based on the number of iterations of the mandelbrot set
  that have been evaluated.&quot;
  [[xcoord ycoord] max-iters]
  (let [num-iters (count (take max-iters (take-while #(&lt;= (mag %) 4) (mandelformula xcoord ycoord))))]
    (if (= max-iters num-iters)
      *set-colour*
      (iter-colour num-iters max-iters))))
</pre></p>
<p>The call to <code>vec</code> is deeper still within the calls to <code>iter-colour</code> and <code>grad-colour</code>:</p>
<p><pre class="brush: javafx;">
(defn grad-colour
  &quot;Returns the colour that is the given fraction of the way between
  the first and second colours given. Returns as a vector of three
  integers between 0 and 255.&quot;
  [colA colB frac]
  (vec (map #(+ (* frac (- %2 %1)) %1) colA colB)))

(defn iter-colour
  &quot;Returns the colour needed to paint a point with the given number
  of iterations&quot;
  [num-iters max-iters]
  (grad-colour *grad-colour-a* *grad-colour-b*
    (/ (double num-iters) max-iters)))
</pre></p>
<p>The reason we see the <code>count</code> and <code>vec</code> calls at the level of the <code>render</code> function is that Clojure (or perhaps the hotspot) appears to inline certain function calls into the calling function. You can see further evidence of this in the above screenshot if you have a look at the <code>divide</code>, <code>add</code> and <code>multiply</code> methods. These are the operations performed by the <code>get-coord</code> function:</p>
<p><pre class="brush: javafx;">
(defn get-coord
  &quot;Returns the coordinates of the given pixel in the complex plane&quot;
  [x y xstart ystart xsize ysize width height]
  [(+ xstart (* (/ x width) xsize))
   (+ ystart (* (/ y height) ysize))])
</pre></p>
<p>You should also see that at the time of the snapshot I took above, the number of invocations of each of the mathematical operations was around 67k which is twice the number of invocations of the <code>count</code> function which makes sense as you can see they are called once for each of the x and y coordinates.</p>
<p>Let&#8217;s dig deeper into the <code>count</code> function.</p>
<p><a href="http://developmentjungle.files.wordpress.com/2009/11/profile-count.png"><img class="aligncenter size-full wp-image-57" title="VisualVM profile of count (click to enlarge)" src="http://developmentjungle.files.wordpress.com/2009/11/profile-count-crop.png?w=700" alt=""   /></a></p>
<p>As you expand the call tree, and if you ignore the <code>clojure.lang</code> methods, you&#8217;ll see calls to <code>take</code>, <code>take-while</code>, <code>iterate</code> and finally <code>mandelformula</code>. Here&#8217;s another mystery of the Clojure call stack: we have a call to <code>iterate</code> before the call to <code>mandelformula</code> and yet in our code we can see iterate is called <em>within</em> the <code>mandelformula</code> function.</p>
<p><pre class="brush: javafx;">
(defn mandelformula [xcoord ycoord]
  &quot;Returns an infinite sequence of vectors containing the values of
  successive iterations of the mandelbrot formula, given a point on
  the complex plane.&quot;
  (iterate
    #(vec (map + (mandel %) [xcoord ycoord]))
    [xcoord ycoord]))
</pre></p>
<p>As far as I can tell, the reason for this is that <code>mandelformula</code> returns a lazy sequence which is not actually evaluated until it is needed. So <code>iterate</code> is used to get the next value in the sequence, while <code>mandelformula</code> actually does the job of calculating what the next value should be.</p>
<p><a href="http://developmentjungle.files.wordpress.com/2009/11/profile-mandelformula.png"><img class="aligncenter size-full wp-image-59" title="Visual VM profile of mandelformula (click to enlarge)" src="http://developmentjungle.files.wordpress.com/2009/11/profile-mandelformula-crop.png?w=700" alt=""   /></a></p>
<p>Drilling down into the <code>mandelformula</code> function we open up a whole can of method calls and it gets suddenly very difficult to map back to the original Clojure code. However we can see there seem to be a large number of sequences created and calls to methods in the <code>clojure.lang.Numbers</code> class taking <code>Objects</code> as their parameters. If we could get the formula to only use primitive types, this could potentially remove a lot of object creation and garbage collection. However, before we start re-working the code, let&#8217;s look at another profiling technique available to us in Clojure.</p>
<h2>Using Clojure Contrib&#8217;s Profile Macros</h2>
<p><a href="http://stuartsierra.com/">Stuart Sierra</a> has made a vast number of contributions to Clojure including the <a href="http://richhickey.github.com/clojure-contrib/profile-api.html">profile</a> library which provides two macros <code>prof</code> and <code>profile</code> to measure the execution time of any block of code. Clojure&#8217;s macro system makes what would normally be a cumbersome task in other languages extremely easy. Let&#8217;s put profiling in our <code>coord-colour</code> function:</p>
<p><pre class="brush: javafx; highlight: [3,4];">
(defn coord-colour
  [[xcoord ycoord] max-iters]
  (let [num-iters (prof :mandel (count (take max-iters (take-while #(&lt;= (mag %) 4) (mandelformula xcoord ycoord)))))]
    (prof :colour (if (= max-iters num-iters)
      *set-colour*
      (iter-colour num-iters max-iters)))))
</pre></p>
<p>We simply wrap the block of code we want to profile around a call to the <code>prof</code> macro and specify a keyword to identify that block of code. Calling the <code>profile</code> macro will then summarise the time taken to evaluate each call to those <code>prof</code> blocks and print a bunch of statistics.</p>
<p><pre class="brush: javafx;">
user=&gt; (time (profile (my-mandelbrot)))
  Name      mean       min       max     count       sum
colour      4875      1117   1091200    300000  1462510112
mandel     71729      2514 100182286    300000 21518722246
&quot;Elapsed time: 31456.673404 msecs&quot;
</pre></p>
<p>Here we can see that the total time taken by the <code>mandel</code> section of the <code>coord-colour</code> function is around 21 seconds (the values above are in nanoseconds) which gives it 68% of the total running time. The time taken to calculate the gradient colour is about 5% of the total running time. These are quite different statistics from what we saw with VisualVM which gave figures of 60% for the <code>count</code> function and 20% for the calls to <code>vec</code>. The discrepancy is most likely due to the fact that the program did not run to completion when I profiled it with VisualVM. The time taken by the <code>count</code> function depends very much on the number of iterations it executes and during the first 25% of the render, most of its calls finish within 4-5 iterations.</p>
<p>In any case, now that we know the source of the slow performance, let&#8217;s turn our attention to optimisation.</p>
<h2>Back to Primitives</h2>
<p>If we want to eliminate boxed numbers while calculating each term of the Mandelbrot formula, then unfortunately that means we will also have to stop being lazy. It&#8217;s not possible to create a lazy sequence of primitives (just yet). This means we will need to calculate all the terms of the Mandelbrot formula in a single function before returning the number of iterations taken.</p>
<p><pre class="brush: javafx;">
(defn mandelformula [x0 y0 max-iters]
  &quot;Applies the mandelbrot formula until max-iters iterations
  are reached, or the magnitude of Z exceeds 2&quot;
  (let [x0 (double x0)
        y0 (double y0)
        max-iters (int max-iters)]
    (loop [x (double x0)
           y (double y0)
           n (int 0)]
      (if (== n max-iters)
        n
        (let [mag (+ (* x x) (* y y))]
          (if (&gt;= mag (double 4))
            n
            (let [new-x (+ x0 (- (* x x) (* y y)))
                  new-y (+ y0 (* (double 2) (* x y)))]
              (recur new-x new-y (inc n)))))))))
</pre></p>
<p>Here is the newly improved function. Note how I explicitly <a href="http://clojure.org/java_interop#toc37">coerce</a> the function parameters to doubles using a <code>let</code>. The intermediate values for each iteration are now defined in a <code>loop</code> and again explicitly coerced. It can be tricky in Clojure to force primitives &#8211; there&#8217;s no static type checking as in Java of course &#8211; but Clojure will throw an exception if you try to pass non-primitive values to a loop that uses coerced parameters. This helps detect the times when Clojure magically autoboxes your primitives behind your back. (One place where I tripped up was thinking that mathematical operators that take multiple arguments would return a primitive when passed primitives, in fact, (* (int 1) (int 2) (int 3)) will return an Integer whereas (* (int 1) (int 2)) returns an <code>int</code>. This is why the calculation of <code>new-y</code> above involves two calls to *).</p>
<p>In the above function, I&#8217;m taking care of calculating all the terms of the mandelbrot formula up to the point where <code>z</code> &gt; 2 or <code>max-iters</code> is reached. This is a bit more than the original <code>mandelformula</code> function so the <code>coord-colour</code> function simplifies to:</p>
<p><pre class="brush: javafx;">
(defn coord-colour
  &quot;Returns a colour for which to draw the given coordinate. If the coordinate
  is within the mandelbrot set, black is returned. Otherwise, a colour within
  a gradient is given based on the number of iterations of the mandelbrot set
  that have been evaluated.&quot;
  [[xcoord ycoord] max-iters]
  (let [num-iters (mandelformula xcoord ycoord max-iters)]
    (if (= max-iters num-iters)
      *set-colour*
      (iter-colour num-iters max-iters)
      )))
</pre></p>
<p>Let&#8217;s see what kind of performance we get now.</p>
<p><pre class="brush: javafx;">
user=&gt; (time (profile (my-mandelbrot)))
  Name      mean       min       max     count       sum
colour      5179      1117   1593220    300000  1553876060
mandel      1787      1396    137448    300000  536248035
&quot;Elapsed time: 10177.274766 msecs&quot;
</pre></p>
<p>Wow, that&#8217;s a 40x speed improvement for the <code>mandel</code> part of our code. This shows how significant keeping object allocations to a minimum can be. However, the two parts of the code we&#8217;re profiling only make up about 2 seconds out of a total of 10 seconds of runtime. Let&#8217;s move our profiling to the <code>render</code> function:</p>
<p><pre class="brush: javafx; highlight: [5,6,7];">
(defn render [xstart ystart xsize ysize width height max-iters wr]
  (dorun
    (map (fn [pixel]
            (let [[x y] pixel]
              (prof :setPixel (.setPixel wr x y
                (prof :int-array (int-array 
                  (prof :coord-colour (coord-colour
                    (get-coord (double x) (double y) xstart ystart xsize ysize width height)
                    max-iters))))))))
           (get-pixels width height))))
</pre></p>
<p>And run the render again:</p>
<p><pre class="brush: javafx;">
user=&gt; (time (profile (my-mandelbrot)))
        Name      mean       min       max     count       sum
coord-colour      6632      3073   1690997    300000  1989613029
   int-array     11402      7263   1706641    300000  3420617714
    setPixel     30688     21790   2191620    300000  9206612546
&quot;Elapsed time: 11283.777407 msecs&quot;
</pre></p>
<p>You can see that <code>setPixel</code> is most costly function, but this is not really a surprise given the other two calls are nested within it. However, even taking the runtime of the nested calls into account, the <code>.setPixel</code> call is taking nearly 6 out of the total 11 seconds (the reason we have an extra 1s of runtime after this run is most likely due to the overhead of profiling another block of code). </p>
<h2>Removing Reflection</h2>
<p>We can see that <code>.setPixel</code> is called on a binding called <code>wr</code> but Clojure (nor us) has no idea what type wr might be. In fact Clojure has to use reflection to determine which method <code>.setPixel</code> refers to. Let&#8217;s turn on reflection warning and load the program again:</p>
<p><pre class="brush: javafx;">
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:87 - call to setPixel can't be resolved.
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:87 - call to setPixel can't be resolved.
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:99 - call to drawImage can't be resolved.
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:105 - call to setPreferredSize can't be resolved.
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:106 - call to add can't be resolved.
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:117 - reference to field getRaster can't be resolved.
Reflection warning, D:\dev\clojure\...\mandelbrot.clj:122 - reference to field repaint can't be resolved.
1:1 user=&gt; 
</pre></p>
<p>We can see that with reflection warning turned on, Clojure complains that it cannot resolve the call to <code>setPixel</code>. We can fix this of course with a type hint, however we must also remember to coerce the parameters into the types expected by the <code>setPixel</code> method:</p>
<p><pre class="brush: javafx; highlight: [1,5];">
(defn render [xstart ystart xsize ysize width height max-iters #^WritableRaster wr]
  (dorun
    (map (fn [pixel]
            (let [[x y] pixel]
              (prof :setPixel (.setPixel wr (int x) (int y)
                (prof :int-array (int-array 
                  (prof :coord-colour (coord-colour
                    (get-coord (double x) (double y) xstart ystart xsize ysize width height)
                    max-iters))))))))
           (get-pixels width height))))
</pre></p>
<p>Running the program again we notice the reflection warning has gone (the others remain but we don&#8217;t care about them as their calls are not made within a loop), and we get a fairly significant speed up:</p>
<p><pre class="brush: javafx;">
user=&gt; (time (profile (my-mandelbrot)))
        Name      mean       min       max     count       sum
coord-colour      6770      3072  108868865    300000  2031060305
   int-array     12263      6704  221714492    300000  3679041832
    setPixel     16247     10057  221746898    300000  4874399625
&quot;Elapsed time: 6739.067116 msecs&quot;
</pre></p>
<p>This now means that the <code>setPixel</code>, <code>int-array</code> and <code>coord-colour</code> sections now take 17%, 25% and 30% of the total elapsed time respectively. These proportions seem pretty even so it&#8217;s possible that our profiling representing a significant portion of that elapsed time. Let&#8217;s run again, this time without making the call to the <code>profile</code> macro:</p>
<p><pre class="brush: javafx;">
user=&gt; (time (my-mandelbrot))
&quot;Elapsed time: 1668.624085 msecs&quot;
</pre></p>
<p>That&#8217;s quite a big drop and it shows how significant the overhead of profiling can be but I&#8217;m hoping that this can be reduced with optimisations to the profiling macros themselves in the future. </p>
<p>We saw earlier how the section of code for calculating a colour gradient was taking about 75% of the time of the <code>mandelformula</code> function. It&#8217;s possible this function could be sped up with more primitive type arithmetic but let&#8217;s try a different, more functional method of optimisation.</p>
<h2>Memoization</h2>
<p>The <code>iter-colour</code> function takes a number between 1 and max-iter and returns a corresponding colour. The fact that there is only a small, fixed number of possible inputs to the function and the output is always the same for a given input, makes it a perfect candidate for <a href="http://clojure.org/api#toc370">memoization</a>. We can simply redefine the function as a memoized version of itself:</p>
<p><pre class="brush: javafx;">
user=&gt; (def iter-colour (memoize iter-colour ))
#'user/iter-colour
user=&gt; (time (my-mandelbrot))
&quot;Elapsed time: 954.501759 msecs&quot;
</pre></p>
<p>We have now managed to improve overall performance by over 30 times. It&#8217;s possible we could repeat these techniques such as inlining the get-pixels function or making the get-coord function use primitives to get a further performance boost. However, as cgrand says, <a href="http://clj-me.cgrand.net/2009/11/18/an-optimization-job-is-never-done/">an optimisation job is never done</a> and for now I believe the performance is &#8220;good enough&#8221;.</p>
<p>The full optimised code can be found <a href="http://github.com/alexspurling/clojure-projects/blob/master/Mandelbrot/src/fast-mandelbrot.clj">on github</a>. Please feel free to submit your own performance optimisations to improve the code even further <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Conclusion</h2>
<p>We&#8217;ve seen how to use profiling tools to peer beneath Clojure&#8217;s dynamic lispy surface and used this knowledge to dramatically improve the performance of our fractal renderer by taking advantage of function inlining, primitive coersions, elimination of reflection and memoization. Hopefully these techniques will be useful to you when improving the performance of your own Clojure programs!</p>
<h3>References</h3>
<p>Inspiration on how to write a Mandelbrot fractal renderer the &#8216;right&#8217; way: <a href="http://briancarper.net/tag/mandelbrot">http://briancarper.net/tag/mandelbrot</a><br />
Performance tips on Clojure: <a href="http://devlog.bigmonachus.org/2009/03/performance-tips-for-clojure.html">http://devlog.bigmonachus.org/2009/03/performance-tips-for-clojure.html</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/developmentjungle.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/developmentjungle.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/developmentjungle.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/developmentjungle.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/developmentjungle.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/developmentjungle.wordpress.com/37/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/developmentjungle.wordpress.com/37/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/developmentjungle.wordpress.com/37/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=developmentjungle.wordpress.com&amp;blog=9851043&amp;post=37&amp;subd=developmentjungle&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://developmentjungle.wordpress.com/2009/11/24/optimising-mandelbrot/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ea60532a61910966b4ee1f60ce5c75c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">alex</media:title>
		</media:content>

		<media:content url="http://developmentjungle.files.wordpress.com/2009/11/clojure-mandelbrot-set-preview.png" medium="image">
			<media:title type="html">Clojure Mandelbrot Set</media:title>
		</media:content>

		<media:content url="http://developmentjungle.files.wordpress.com/2009/11/profile-render.png" medium="image">
			<media:title type="html">VisualVM profile of render</media:title>
		</media:content>

		<media:content url="http://developmentjungle.files.wordpress.com/2009/11/profile-count-crop.png" medium="image">
			<media:title type="html">VisualVM profile of count (click to enlarge)</media:title>
		</media:content>

		<media:content url="http://developmentjungle.files.wordpress.com/2009/11/profile-mandelformula-crop.png" medium="image">
			<media:title type="html">Visual VM profile of mandelformula (click to enlarge)</media:title>
		</media:content>
	</item>
		<item>
		<title>Rendering the Mandelbrot Set in Clojure</title>
		<link>http://developmentjungle.wordpress.com/2009/11/14/rendering-the-mandelbrot-set-in-clojure/</link>
		<comments>http://developmentjungle.wordpress.com/2009/11/14/rendering-the-mandelbrot-set-in-clojure/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 20:08:11 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[programming-languages]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[walk through]]></category>

		<guid isPermaLink="false">http://developmentjungle.wordpress.com/?p=3</guid>
		<description><![CDATA[Clojure is a functional language that brings dynamic types and lisp syntax to the JVM. It has a number of features that make it interesting which will be the subject of another post but for now, let&#8217;s dive right into some code. The Mandelbrot Set The Mandelbrot set is an example of a fractal which [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=developmentjungle.wordpress.com&amp;blog=9851043&amp;post=3&amp;subd=developmentjungle&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-15" title="Clojure Mandelbrot Set" src="http://developmentjungle.files.wordpress.com/2009/11/clojure-mandelbrot-set-preview.png?w=700" alt="Clojure Mandelbrot Set"   /><a href="http://www.clojure.org">Clojure</a> is a functional language that brings dynamic types and lisp syntax to the JVM. It has a number of features that make it interesting which will be the subject of another post but for now, let&#8217;s dive right into some code.</p>
<h2>The Mandelbrot Set</h2>
<p>The <a href="http://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot set</a> is an example of a fractal which is basically something that can be described using a simple formula and yet exhibit fascinating levels of detail and beauty. I thought it would be  a good application to get me started learning Clojure.<br />
<span id="more-3"></span><br />
The Mandelbrot formula is:</p>
<p><strong>Z = Z<sup>2</sup> + C</strong></p>
<p>Where <strong>Z</strong> is a complex number and <strong>C</strong> is a constant. To find out whether or not <strong>C</strong> is in the set, we apply the formula iteratively until the magnitude of <strong>Z</strong> becomes larger than 2, or we reach a certain number of maximum iterations.</p>
<p>Most 2D fractals are described mathematically using complex numbers which are just like regular (real) numbers but with an added 2nd dimension. They can be represented by two regular numbers so another way to describe the formula above might be:</p>
<p><strong>[x, y] = [x, y]<sup>2</sup> + [a, b]</strong></p>
<p>Where <strong>[a, b]</strong> is equivalent to <strong>C</strong> and represents the coordinates on the complex plane we&#8217;re interested in. By applying the formula we can find out whether or not <strong>C</strong> is in the Mandelbrot set. If it is, we draw it with a black pixel, otherwise with some other colour depending the number of iterations taken by the formula.</p>
<h2>Defining a Functional Mandelbrot Set</h2>
<p>Let&#8217;s try to write this in Clojure code. First of all, how do you square a complex number? First let&#8217;s represent <strong>Z</strong> as a vector of regular numbers <strong>[x, y]</strong>. To square them we just apply the formula:</p>
<p><strong>[x, y]<sup>2</sup> = [x<sup>2</sup> - y<sup>2</sup>, 2xy]</strong></p>
<p><strong> </strong>In Clojure, it looks like this:</p>
<p><pre class="brush: javafx;">
(defn mandel [[x y]]
  [(- (* x x) (* y y)) (* 2 x y)])
</pre></p>
<p>But this represents just half of the Mandelbrot formula, we need to add that constant<strong> C</strong> and also somehow call our <code>mandel</code> function iteratively. Normally, in an imperative language, this would be easy. We just assign C to our starting value, then calculate Z in a for loop. In Clojure, it&#8217;s a bit different:</p>
<p><pre class="brush: javafx;">
(defn mandelformula [xcoord ycoord]
  (iterate
    #(vec (map + (mandel %) [xcoord ycoord]))
    [xcoord ycoord]))
</pre></p>
<p>This function uses the <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/iterate">iterate</a></code> function to create successive calls to the <code>mandel</code> function passing our initial starting value <strong>[xcoord, ycoord]</strong> which represents <strong>C</strong> in the original formula. The <code>mandel</code> function is actually wrapped in an anonymous function which adds the return value to the initial value hence giving us the <strong>Z</strong><strong><sup>2</sup></strong><strong> + C</strong>. The reason we have to use <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/map">map</a></code> is that we cannot directly add the two vectors together. The individual <strong>x</strong> and <strong>y</strong> values must be added separately and then constructed back into a vector with the <code>vec</code> function.</p>
<p>That&#8217;s quite a dense piece of code but I think represents the mathematical version of the formula fairly well. It&#8217;s certainly not the fastest implementation but the goal of functional programming is to favour correctness and readability rather than performance. The great thing about this implementation is that that <code>iterate</code> function returns a lazy infinite sequence. This is very much like the mathematical definition of the formula given at the start; it says nothing about how many times we&#8217;re actually going to keep applying the formula.</p>
<p>The next part of the definition of the set says that we need to apply the formula to a given point until either the magnitude of <strong>Z</strong> becomes greater than 2, or we reach a given number of iterations.</p>
<p><pre class="brush: javafx;">
(defn mag [[x y]]
 (+ (* x x) (* y y)))

(take 50 (take-while #(&lt;= (mag %) 4) (mandelformula xcoord ycoord)))
</pre></p>
<p>Firstly, we define the function <code>mag</code> which returns the magnitude (actually, the magnitude squared) of the given vector pair. Next we use this function with the <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/take-while">take-while</a></code> function so we&#8217;ll only evaluate the terms of the mandelbrot formula while the value of each term is less than or equal to 4 (we&#8217;ve squared 2 to avoid having to perform an expensive square root in the <code>mag</code> function). <code>take-while</code> returns another lazy sequence (which might also be infinite) so we use <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/take">take</a></code> to restrict the number of terms evaluated to 50.</p>
<p>Now we&#8217;re pretty much done with all the maths stuff. All we need to do is count the number of terms calculated and from that number, calculate a colour.</p>
<p><pre class="brush: javafx;">
(defn coord-colour
  [[xcoord ycoord] max-iters]
  (let [num-iters (count (take max-iters (take-while #(&lt;= (mag %) 4) (mandelformula xcoord ycoord))))]
    (if (= max-iters num-iters)
    *set-colour*
    (iter-colour num-iters max-iters))))
</pre></p>
<p>This function takes a coordinate, a defined number of maximum iterations and returns the colour that the coordinate should be rendered with by applying the Mandelbrot formula. You can see that we&#8217;re assigning <strong>num-iters</strong> to the count of the terms returned by our sequence calculated earlier. We then compare <strong>num-iters</strong> with <strong>max-iters</strong>, if they are equal, then the given coordinate is likely to be in the Mandelbrot set so we return <strong>*set-colour*</strong>. If <strong>num-iters</strong> is less than <strong>max-iters</strong> then the coordinate cannot be within the set so we pass the values to another function <code>iter-colour</code> which applies a gradient to the colours.</p>
<h2>Calculating a Colour Gradient</h2>
<p>First of all we define three vectors representing the colours we want to draw with as RGB values.</p>
<p><pre class="brush: javafx;">
;; Colours used to draw the set
(def *grad-colour-a* [255, 255, 0]) ;yellow
(def *grad-colour-b* [0, 0, 255]) ;blue
(def *set-colour* [0, 0, 0]) ;black
</pre></p>
<p>We want to calculate a gradient colour such that if <strong>num-iters</strong> is 0, we return yellow, if it is equal to <strong>max-iters</strong> we return blue and if it is somewhere in between, we return a mix between the two colours.</p>
<p><pre class="brush: javafx;">
(defn grad-colour
  &quot;Returns the colour that is the given fraction of the way between
  the first and second colours given. Returns as a vector of three
  integers between 0 and 255.&quot;
  [colA colB frac]
  (vec (map #(+ (* frac (- %2 %1)) %1) colA colB)))

(defn iter-colour
  &quot;Returns the colour needed to paint a point with the given number
  of iterations&quot;
  [num-iters max-iters]
  (grad-colour *grad-colour-a* *grad-colour-b*
    (/ (double num-iters) max-iters)))
</pre></p>
<p>The <code>iter-colour</code> function calculates the number of iterations as a fraction of the maximum number of iterations to give a value between 0 and 1 and passes this along with the two colours to the <code>grad-colour</code> function. This function simply calculates the difference between each of the R, G and B values of the two colours and weights it by multiplying by <strong>frac</strong>. Again, similar to how we calculate the sum of a vector in the <code>mandelformula</code> function, we use <code>map</code> to apply this calculation to each of the three values in the two vectors.</p>
<h2>Surfing the Complex Plane</h2>
<p>Now we have all we need to calculate the colour of a given coordinate on the complex plane, we&#8217;re close to being able to render a fractal in Clojure! But how do we go from the pixels you find on your screen to the mathematical coordinates of the complex plane? Clearly, we need another function.</p>
<p><pre class="brush: javafx;">
(defn get-coord
  &quot;Returns the coordinates of the given pixel in the complex plane&quot;
  [x y xstart ystart xsize ysize width height]
  [(+ xstart (* (/ x width) xsize))
  (+ ystart (* (/ y height) ysize))])
</pre></p>
<p>This function takes the x and y <code>pixel</code> coordinates and returns the corresponding <code>complex</code> coordinates. The other parameters are the complex coordinate of the top-left of our screen (<strong>xstart</strong> and <strong>ystart</strong>), the complex dimensions of the area we&#8217;re drawing (<strong>xsize</strong> and <strong>ysize</strong>) and the dimensions of the area we are drawing in pixels (<strong>width</strong> and <strong>height</strong>).</p>
<p>Now all we need is a way to get all the pixels in our drawing area as vectors to pass on to the this function.</p>
<p><pre class="brush: javafx;">
(defn get-pixels [width height]
  (for [y (range height) x (range width)]
    [x y]))
</pre></p>
<p>This function returns a lazy sequence of pixel coordinates for the given width and height. We just need to map the <code>get-coord</code> function onto this sequence and we&#8217;ll have a lazy sequence of <em>all</em> the complex coordinates in our drawing area. Then all that&#8217;s left is to get the colour of each of those complex coordinates (according the mandelbrot formula) and assign the colour to the corresponding pixel.</p>
<p><pre class="brush: javafx;">
(defn render [xstart ystart xsize ysize width height max-iters wr]
  (dorun
    (pmap (fn [pixel]
            (let [[x y] pixel]
              (.setPixel wr x y
                (int-array (coord-colour
                  (get-coord (double x) (double y) xstart ystart xsize ysize width height)
                  max-iters)))))
          (get-pixels width height))))
</pre></p>
<p>Here we are in the heart of the fractal renderer. Note that we use <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/pmap">pmap</a></code> to process the sequence of pixels which works just like <code>map</code> but runs across multiple threads which allows us to make the most of multi-core system and render each pixel in parallel. Also, we must use <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/dorun">dorun</a></code> because <code>get-pixels</code> returns a lazy sequence, so <code>pmap</code> is forced to actually process each pixel (rather than return a lazy sequence as it would do normally). Finally, the colour returned by each call to <code>coord-colour</code> is converted into a Java int[] array so that it can be passed to the <code>.setPixel</code> function of <strong>wr</strong> which is an instance of a <code>WritableRaster</code>.</p>
<p>Note also how we <code>coerce</code> the pixel values of <strong>x</strong> and <strong>y</strong> into doubles. This is because by default, Clojure will use arbitrary precision using Java&#8217;s BigDecimal class which would incur a huge performance hit when it came to applying the formula. Coercing to double ensures we use either double primitives or boxed Double objects.</p>
<h2>Setting up the Swing Stuff</h2>
<p>All the remaining code is to initialise the Java Swing components needed to display the image generated.</p>
<p><pre class="brush: javafx;">
(defn get-img [width height]
  (BufferedImage. width height (BufferedImage/TYPE_INT_RGB)))

(defn get-panel [width height img]
  (proxy [JPanel] [] (paint [g] (.drawImage g img 0 0 (Color/red) nil))))

(defn construct-frame [width height panel]
  &quot;Creates and displays a JFrame of the given dimensions with
  the panel added to it&quot;
  (let [frame (JFrame.)]
    (.setPreferredSize panel (Dimension. width height))
    (doto frame
      (.add panel)
      .pack
      (.setLocationRelativeTo nil)
      .show)))

(defn mandelbrot [xstart ystart xsize ysize width height max-iters]
  &quot;Returns a function to render the mandelbrot set with the
  given parameters on a frame&quot;
  (let [img (get-img width height)
        panel (get-panel width height img)
        wr (.getRaster img)]
    (construct-frame width height panel)
    (fn []
      (do
        (render xstart ystart xsize ysize width height max-iters wr)
        (.repaint panel)))))
</pre></p>
<p>We have defined a number of functions for creating the Swing components and also a function for putting them all together called <code>mandelbrot</code>. Notice, rather than call <code>render</code> immediately, the <code>mandelbrot</code> creates and returns an anonymous function instead. This function is actually a <code>closure</code> which means we can call it repeatedly without having to keep passing in the parameters for the window size and number of iterations. When running a program in a REPL, being able to call individual parts of your code can be very handy.</p>
<p>Finally, we assign the function to a var, and then call it!</p>
<p><pre class="brush: javafx;">
(def my-mandelbrot (mandelbrot -2 -1.25 3 2.5 1200 1000 50))

(future (my-mandelbrot))
</pre></p>
<p>We wrap the call to <code>my-mandelbrot</code> in a <code><a href="http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/future">future</a></code> which returns immediately and then executes the function passed to it in a separate thread. The reason for this is that rendering the fractal can take a significant amount of time. Using a <code>future</code> allows you to continue to use the REPL while the rendering happens in the background which can be helpful for debugging or general development. After about 30 seconds or so, you&#8217;ll see something like this:</p>
<p><img class="aligncenter size-full wp-image-17" title="Clojure Mandelbrot Set" src="http://developmentjungle.files.wordpress.com/2009/11/clojure-mandelbrot-set.png?w=700" alt="Mandelbrot Set rendered in Clojure"   /></p>
<h2>Conclusion</h2>
<p>We&#8217;ve seen how to create a working fractal rendering program by building on mathematical formulas and making use of Clojure features such as lazy, infinite sequences, parallel processing and closures to do it. These features allow us to keep the code close to the problem domain and hopefully, improve its readability and correctness. In the <a href="/2009/11/24/optimising-mandelbrot/">next post</a> we&#8217;ll see how to profile the renderer and <em>drastically</em> improve its performance.</p>
<p>The full source code can be found <a href="http://github.com/alexspurling/clojure-projects/blob/master/Mandelbrot/src/mandelbrot.clj">here on github</a>.</p>
<p>Stay tuned for more Clojure goodness in the future!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/developmentjungle.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/developmentjungle.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/developmentjungle.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/developmentjungle.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/developmentjungle.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/developmentjungle.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/developmentjungle.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/developmentjungle.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=developmentjungle.wordpress.com&amp;blog=9851043&amp;post=3&amp;subd=developmentjungle&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://developmentjungle.wordpress.com/2009/11/14/rendering-the-mandelbrot-set-in-clojure/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/ea60532a61910966b4ee1f60ce5c75c1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">alex</media:title>
		</media:content>

		<media:content url="http://developmentjungle.files.wordpress.com/2009/11/clojure-mandelbrot-set-preview.png" medium="image">
			<media:title type="html">Clojure Mandelbrot Set</media:title>
		</media:content>

		<media:content url="http://developmentjungle.files.wordpress.com/2009/11/clojure-mandelbrot-set.png" medium="image">
			<media:title type="html">Clojure Mandelbrot Set</media:title>
		</media:content>
	</item>
	</channel>
</rss>
