Commit 816b587f by Simon Marlow

Document the new SPARKS statistic, and xref from the parallelism section

parent b7ea7671
 ... ... @@ -114,10 +114,10 @@ All these features are described in the papers mentioned earlier. infixr 0 `par` infixr 1 `seq` infixr 1 `pseq` par :: a -> b -> b seq :: a -> b -> b par :: a -> b -> b pseq :: a -> b -> b The expression (x `par` y) sparks the evaluation of x ... ... @@ -136,24 +136,35 @@ import Control.Parallel nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (seq n2 (n1 + n2 + 1)) | otherwise = par n1 (pseq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2) For values of n greater than 1, we use par to spark a thread to evaluate nfib (n-1), and then we use seq to force the and then we use pseq to force the parent thread to evaluate nfib (n-2) before going on to add together these two subexpressions. In this divide-and-conquer approach, we only spark a new thread for one branch of the computation (leaving the parent to evaluate the other branch). Also, we must use seq to ensure that the parent will evaluate pseq to ensure that the parent will evaluate n2 before n1 in the expression (n1 + n2 + 1). It is not sufficient to reorder the expression as (n2 + n1 + 1), because the compiler may not generate code to evaluate the addends from left to right. Note that we use pseq rather than seq. The two are almost equivalent, but differ in their runtime behaviour in a subtle way: seq can evaluate its arguments in either order, but pseq is required to evaluate its first argument before its second, which makes it more suitable for controlling the evaluation order in conjunction with par. When using par, the general rule of thumb is that the sparked computation should be required at a later time, but not too soon. Also, the sparked computation should not be too small, otherwise ... ... @@ -161,6 +172,10 @@ nfib n | n <= 1 = 1 amount of parallelism gained. Getting these factors right is tricky in practice. It is possible to glean a little information about how well par is working from the runtime statistics; see . More sophisticated combinators for expressing parallelism are available from the Control.Parallel.Strategies module. ... ...
 ... ... @@ -531,6 +531,8 @@ Generation 0: 67 collections, 0 parallel, 0.04s, 0.03s elapsed Generation 1: 2 collections, 0 parallel, 0.03s, 0.04s elapsed SPARKS: 359207 (557 converted, 149591 pruned) INIT time 0.00s ( 0.00s elapsed) MUT time 0.01s ( 0.02s elapsed) GC time 0.07s ( 0.07s elapsed) ... ... @@ -588,6 +590,17 @@ that generation. The SPARKS statistic refers to the use of Control.Parallel.par and related functionality in the program. Each spark represents a call to par; a spark is "converted" when it is executed in parallel; and a spark is "pruned" when it is found to be already evaluated and is discarded from the pool by the garbage collector. Any remaining sparks are discarded at the end of execution, so "converted" plus "pruned" does not necessarily add up to the total. Next there is the CPU time and wall clock time elapsedm broken ... ...
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!