[Haskell-cafe] a parallel mapM?

Greg Fitzgerald garious at gmail.com
Fri Sep 28 20:01:01 CEST 2012


I'm new to concurrent programming in Haskell.  I'm looking for a
drop-in replacement for 'mapM' to parallelize a set of independent IO
operations.  I hoped 'mapConcurrently' might be it, but I need
something that will only spawn as many threads as I have CPUs
available [1].

I also tried Control.Parallel.Strategies [2].  While that route works,
I had to use unsafePerformIO.  Considering that IO is for sequencing
effects and my IO operation doesn't cause any side-effects (besides
hogging a file handle), is this a proper use of unsafePerformIO?


Attempt 1
--------------

import System.Process(readProcess)
import Control.Concurrent.Async(mapConcurrently)

main :: IO [String]
main = mapConcurrently (\n -> readProcess "echo" ["test: " ++ show n]
"") [0..1000]


$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.6.1

$ runghc test.hs
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: runInteractiveProcess: pipe: Too many open files
test.hs: echo: createProcess: resource exhausted (Too many open files)


Attempt 2
--------------

import System.Process(readProcess)
import Control.Parallel.Strategies(parMap, rpar)
import System.IO.Unsafe(unsafePerformIO)

main :: IO [String]
main = myMapConcurrently (\n -> readProcess "echo" ["test: " ++ show
n] "") [0..1000]
  where
    myMapConcurrently f = return . parMap rpar (unsafePerformIO . f)

$ runghc test.hs > /dev/null && echo Success
Success


Thanks,
Greg



More information about the Haskell-Cafe mailing list