From: Simon Peyton-Jones &lt;<a href="mailto:simonpj@microsoft.com">simonpj@microsoft.com</a>&gt;<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

<br>
Friends<br>
<br>
I&#39;m giving a talk at a developer conference in London on Friday 18th, about parallel programming in Haskell.<br>
        <a href="http://skillsmatter.com/event/scala/functionalpx-2011/ad-1382" target="_blank">http://skillsmatter.com/event/scala/functionalpx-2011/ad-1382</a><br>
<br>
I know that some of you have been using Haskell for parallel or concurrent programming quite a bit, so this email is just to ask<br>
<br>
        could you contribute a little vignette or story<br>
        about using Haskell in a *parallel/concurrent* application<br>
        that I could use to illustrate my talk?<br></blockquote><div><br>I have a physical-model-based audio synthesis application I wanted to convert from an off-line renderer into a real-time engine.  I decided upon a concurrent architecture with an interface thread, an engine thread, and an output thread, using STM for communication.  It only took a couple hours to make the conversion, most of which was spent modifying the synthesis to work in blocks instead of a single run.<br>
<br>I&#39;m particularly happy with this snippet, where the engine collects input from the interface thread:<br><br>  readStrikeVar = do<br>    ct &lt;- getCPUTime<br>    atomically $ rsv&#39; ct `orElse` return []<br>   -- if the read fails, return an empty list because we can&#39;t afford to wait.<br>
   -- the strikes will eventually catch up...<br>  rsv&#39; ct = do<br>    strikes &lt;- readTVar tstrikes<br>    let carry = map (updateCarry blockdur) $ filter carryOver strikes<br>    writeTVar tstrikes carry<br>    writeTVar tsync ct<br>
    return (reverse strikes)<br><br>This code is the most complicated part of the communication scheme, nearly everything else is at the level of &quot;readTVarIO&quot;.  A nice feature is that the engine doesn&#39;t block waiting for the interface.  If the transaction fails because the interface is updating the TVar, the engine moves ahead and can catch up later.<br>
<br>On my dual-core macbook, performance is perhaps slightly disappointing compared to the offline renderer which is single-threaded and not parallelized.  With one simulation the offline renderer will generate 5 seconds of audio in about 3.3seconds at 100% CPU usage, giving me the equivalent of 66% CPU over 5 seconds.  The realtime renderer consistently occupies about 171% CPU for the same simulation.  A different simulation has a runtime of 4.4 seconds and realtime usage of 191%.  Of course there&#39;s going to be some overhead, but I hope to improve this by changing the way data is fed to the engine to a TChan, and also running threadscope to make sure threads yield at the proper times.<br>
<br>Speaking of which, threadscope is an awesome tool and deserves a mention.<br><br>John L.<br></div></div>