Parallelism

The Par monad (monad-par) offers deterministic parallelism with explicit dataflow. massiv and accelerate (GPU) provide data-parallel arrays. Repa is older.

Parallelism is deterministic in pure code: the result is the same regardless of scheduling.

-- Pure parallelism: evaluation strategies (parallel package)
import Control.Parallel.Strategies

fib :: Int -> Integer
fib n = if n < 2 then toInteger n else fib (n - 1) + fib (n - 2)

main :: IO ()
main = do
  let results = map fib [25 .. 35] `using` parList rdeepseq   -- evaluate list elements in parallel
  print (sum results)
  let (a, b) = runEval $ do
        x <- rpar (fib 33)                                     -- spark in parallel
        y <- rseq (fib 32)                                     -- evaluate now
        _ <- rseq x
        pure (x, y)
  print (a + b)
  print (sum (parMap rdeepseq fib [20 .. 30]))
ghc -O2 -threaded -rtsopts Main.hs
./Main +RTS -N4 -s           # use 4 cores; -s prints GC and spark statistics
threadscope Main.eventlog    # visualize parallel execution (compile with -eventlog, run with +RTS -l)