Check out the parallel combinators in parallel-io: <a href="http://hackage.haskell.org/packages/archive/parallel-io/0.3.2/doc/html/Control-Concurrent-ParallelIO-Global.html">http://hackage.haskell.org/packages/archive/parallel-io/0.3.2/doc/html/Control-Concurrent-ParallelIO-Global.html</a><div>
<br><div class="gmail_quote">On Fri, Sep 28, 2012 at 1:01 PM, Greg Fitzgerald <span dir="ltr">&lt;<a href="mailto:garious@gmail.com" target="_blank">garious@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I&#39;m new to concurrent programming in Haskell.  I&#39;m looking for a<br>
drop-in replacement for &#39;mapM&#39; to parallelize a set of independent IO<br>
operations.  I hoped &#39;mapConcurrently&#39; might be it, but I need<br>
something that will only spawn as many threads as I have CPUs<br>
available [1].<br>
<br>
I also tried Control.Parallel.Strategies [2].  While that route works,<br>
I had to use unsafePerformIO.  Considering that IO is for sequencing<br>
effects and my IO operation doesn&#39;t cause any side-effects (besides<br>
hogging a file handle), is this a proper use of unsafePerformIO?<br>
<br>
<br>
Attempt 1<br>
--------------<br>
<br>
import System.Process(readProcess)<br>
import Control.Concurrent.Async(mapConcurrently)<br>
<br>
main :: IO [String]<br>
main = mapConcurrently (\n -&gt; readProcess &quot;echo&quot; [&quot;test: &quot; ++ show n]<br>
&quot;&quot;) [0..1000]<br>
<br>
<br>
$ ghc --version<br>
The Glorious Glasgow Haskell Compilation System, version 7.6.1<br>
<br>
$ runghc test.hs<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: runInteractiveProcess: pipe: Too many open files<br>
test.hs: echo: createProcess: resource exhausted (Too many open files)<br>
<br>
<br>
Attempt 2<br>
--------------<br>
<br>
import System.Process(readProcess)<br>
import Control.Parallel.Strategies(parMap, rpar)<br>
import System.IO.Unsafe(unsafePerformIO)<br>
<br>
main :: IO [String]<br>
main = myMapConcurrently (\n -&gt; readProcess &quot;echo&quot; [&quot;test: &quot; ++ show<br>
n] &quot;&quot;) [0..1000]<br>
  where<br>
    myMapConcurrently f = return . parMap rpar (unsafePerformIO . f)<br>
<br>
$ runghc test.hs &gt; /dev/null &amp;&amp; echo Success<br>
Success<br>
<br>
<br>
Thanks,<br>
Greg<br>
<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br></div>