From: Simon Peyton-Jones <simonpj@microsoft.com>

Friends

I'm giving a talk at a developer conference in London on Friday 18th, about parallel programming in Haskell.
       http://skillsmatter.com/event/scala/functionalpx-2011/ad-1382

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

       could you contribute a little vignette or story
       about using Haskell in a *parallel/concurrent* application
       that I could use to illustrate my talk?

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.

I'm particularly happy with this snippet, where the engine collects input from the interface thread:

  readStrikeVar = do
    ct <- getCPUTime
    atomically $ rsv' ct `orElse` return []
   -- if the read fails, return an empty list because we can't afford to wait.
   -- the strikes will eventually catch up...
  rsv' ct = do
    strikes <- readTVar tstrikes
    let carry = map (updateCarry blockdur) $ filter carryOver strikes
    writeTVar tstrikes carry
    writeTVar tsync ct
    return (reverse strikes)

This code is the most complicated part of the communication scheme, nearly everything else is at the level of "readTVarIO".  A nice feature is that the engine doesn'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.

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'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.

Speaking of which, threadscope is an awesome tool and deserves a mention.

John L.