liveBook · Manning

Rpar

As explained in Learn Haskell by Example

rpar is a Haskell parallel-evaluation combinator that sparks evaluation of an argument while returning an Eval computation.

`rpar` is an evaluation strategy from `Control.Parallel.Strategies`. It creates a spark for an argument: a request that its evaluation may run in parallel, while the surrounding `Eval` computation can continue. Use it when independent pure work can overlap without changing the algorithm’s result. section 13.4.2 section 13.5

A strategy describes how a value should be evaluated. `r0` performs no evaluation, `rseq` evaluates an argument, `rpar` sparks parallel evaluation, and `rdeepseq` fully evaluates an argument. Evaluation with `rseq` reaches weak head normal form, so list elements can remain unevaluated thunks; `rdeepseq` instead forces normal form. section 13.4.2

Spark one value

Run an `Eval` computation with `runEval`. Binding the result of `rpar x` creates a spark for `x`, but returning does not wait for that evaluation to finish. runEval $ do x' <- rpar x return x' section 13.4.3

A spark points to a thunk and is placed in a spark pool. Haskell execution contexts (HECs), managed by the runtime system in operating-system threads, take sparks from that pool using work stealing. A spark may fizzle if its result is demanded before parallel evaluation finishes, or be a dud if its value was already evaluated. section 13.4.3

Figure 13.5 Haskell execution contexts and spark pools
figure

The diagram relates `rpar` to the spark pool and the HECs that can evaluate queued sparks in parallel. section 13.4.3

Spark every element of a mapped list

`evalList rpar` applies `rpar` to each list element. It can be attached with `using` or passed to `withStrategy`. map (^ 100) [1 .. 1000] `using` evalList rpar withStrategy (evalList rpar) $ map (^ 100) [1 .. 1000] section 13.4.3

Avoid treating one spark per tiny item as an automatic speedup:

  • Too many sparks can overflow the spark pool, leaving parallel execution ineffective. section 13.4.3 section 13.5
  • Split work into larger chunks, then evaluate those chunks in parallel; a vector strategy can use `parListChunk` with `rseq` for chunk evaluation. section 13.4.3 section 13.5
  • Do not immediately force the value sequentially after sparking it, since that defeats the purpose of parallel evaluation. section 13.4.3

For image-style mapping over a vector, chunking reduces a very large spark count to a bounded number of larger jobs. This keeps the pure mapping design while making the evaluation strategy, rather than the image-processing algorithm, responsible for parallel execution. section 13.4.3 section 13.5

How Learn Haskell by Example covers it

How deep it goes
Explains sparks, HEC scheduling, fizzled and dud sparks, then develops list and chunked-vector strategies.
Examples
Demonstrates a single `runEval` spark, parallel exponentiation over a list, and chunked vector mapping for pixels.
What it assumes
Introduces lazy evaluation through thunks and weak head normal form while using `Eval`-based Haskell code.
What you can do after
Apply it via `Control.Parallel.Strategies` to spark independent work and choose chunked strategies when spark counts become excessive.
How it connects
Connects `rpar` with `Eval`, `runEval`, `rseq`, `rdeepseq`, weak head normal form, thunks, and `Strategy`.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.