[Haskell-cafe] Re: Parallel combinator, performance advice
haskell at list.mightyreason.com
Tue Apr 7 09:48:45 EDT 2009
Neil Mitchell wrote:
> Sorry, accidentally sent before finishing the response! I also noticed
> you sent this directly to me, not to -cafe, was that intentional?
The mail/news gateway makes it look like that, but I also sent to the mailing list.
> You mean something like:
> parallel_ xs =
> sem <- createSemapore (length xs)
> enqueue [x >> signalSemapore sem | x <- xs]
> waitOnSemaphore sem
> I thought of something like this, but then the thread that called
> parallel_ is blocked, which means if you fire off N threads you only
> get N-1 executing. If you have nested calls to parallel, then you end
> up with thread exhaustion. Is there a way to avoid that problem?
Your parallel_ does not return until all operations are finished.
> parallel_ (x:xs) = do
> ys <- mapM idempotent xs
> mapM_ addParallel ys
> sequence_ $ x : reverse ys
By the way, there is no obvious reason to insert "reverse" there.
What I meant was something like:
> para  = return ()
> para [x] = x
> para xs = do
> q <- newQSemN 0
> let wrap x = finally x (signalQSemN q 1)
> go [y] n = wrap x >> waitQSemN q (succ n)
> go (y:ys) n = addParallel (wrap y) >> go ys $! succ n
> go xs 0
This is nearly identical to your code, and avoid creating the MVar for each
operation. I use "finally" to ensure the count is correct, but if a worker
threads dies then bas things will happen. You can replace finally with (>>) if
speed is important.
This is also lazy since the length of the list is not forced early.
More information about the Haskell-Cafe