Haskell has a powerful concurrency library which is surprisingly easy to use. The Control.Concurrent library is shipped with the standard installation of ghc and provides everything needed to get started.
As a small test I want to write a programme which reads numbers from stdin, spawns a new process to calculate the Fibonacci number for each input on a different CPU and prints the result to stdout.
First we need a function which is called when spawning a new process, which should calculate the result and print it to the console. In my case this is a simple IO Monad, which gets a MVar as it’s first argument. The function will wait for input from the MVar and then call the Fibonacci function.
This MVar can be thought of as a synchronised box where a thread can store a value and another thread can read from it. So MVars are just the poor men’s message channel which can hold one value at the time only. Of course there are also real channels in Haskell which act like the message queues in Scala or Erlang, see Control.Concurrent.Chan for more informations.
printResult mvar = do
value <- takeMVar mvar
print $ "fib(" ++ show value ++ ")=" ++ show (fib value)
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
Now we need to read the input from stdin, create a MVar object and invoke the printResult function. The cool thing about Haskell is the forkIO function which is really convenient. It takes an arbitrary IO expr and invokes it in a new thread:
import Control.Monad -- needed for "forever"
import System.Exit -- needed for exitSuccess
main = forever $ do
line <- getLine
when (line == "quit") exitSuccess
mvar <- newEmptyMVar
forkIO $ printResult mvar
putMVar mvar (read line :: Integer)
Now we have to compile our programme with the “-threaded” flag:
ghc -threaded fib.hs -o fib
The RTS allows us now to define the number of processors the application runs on with the -Nnum flag. If I want to use three processors for parallelisation I can run the programme simply with:
./fib +RTS -N4