Difference between revisions of "Sequential ordering of evaluation"

From HaskellWiki
Jump to navigation Jump to search
(Various changes for more consistency with other H. wiki articles)
(Earlier quote added, existing quote replaced, formatting simplified)
 
Line 4: Line 4:
 
such an ordering:
 
such an ordering:
   
<blockquote>''While we focus mainly on the implementation, our work has had some impact on the programming model: we identify the need for pseq as well as seq (Section 2.1), and we isolated a signficant difficulty in the "strategies" approach to writing parallel programs (Section 7).''</blockquote>
 
   
  +
<blockquote>
* [https://www.cs.tufts.edu/~nr/cs257/archive/simon-peyton-jones/multicore-ghc.pdf Runtime Support for Multicore Haskell]; Simon Marlow, Simon Peyton Jones and Satnam Singh.
 
  +
The <code>seq</code> combinator implements sequential composition. When the expression <code>e1 ‘seq‘ e2</code> is evaluated, <code>e1</code>
  +
is evaluated to weak head normal form first, and then the value of <code>e2</code> is returned. In the following parallel <code>nfib</code>
  +
function, <code>seq</code> is used to force the evaluation of <code>n2</code> before the addition takes place. This is because Haskell does not
  +
specify which operand is evaluated first, and if <code>n1</code> was evaluated before <code>n2</code>, there would be no parallelism.
  +
  +
<haskell>
  +
nfib :: Int -> Int
  +
nfib n | n <= 1 = 1
  +
| otherwise = n1 ‘par‘ (n2 ‘seq‘ n1 + n2 + 1)
  +
where
  +
n1 = nfib (n-1)
  +
n2 = nfib (n-2)
  +
</haskell>
  +
  +
:<small>[https://web.archive.org/web/20040228202402/http://www.dcs.gla.ac.uk/fp/workshops/fpw96/Trinder.pdf Accidents always Come in Threes: A Case Study of Data-intensive Programs in Parallel Haskell] (page 2 of 14).</small>
  +
</blockquote>
  +
  +
  +
<blockquote>
  +
<b>2.1 The need for</b><code>pseq</code>
  +
  +
The <code>pseq</code> combinator is used for sequencing; informally, it
  +
evaluates its first argument to weak-head normal form, and then evaluates
  +
its second argument, returning the value of its second argument.
  +
Consider this definition of <code>parMap</code>:
  +
  +
<haskell>
  +
parMap f [] = []
  +
parMap f (x:xs) = y ‘par‘ (ys ‘pseq‘ y:ys)
  +
where y = f x
  +
ys = parMap f xs
  +
</haskell>
  +
  +
The intention here is to spark the evaluation of <code>f x</code>, and then
  +
evaluate <code>parMap f xs</code>, before returning the new list <code>y:ys</code>. The
  +
programmer is hoping to express an <i>ordering</i> of the evaluation: <i>first</i>
  +
spark <code>y</code>, <i>then</i> evaluate <code>ys</code>.
  +
 
:<small>[https://www.cs.tufts.edu/~nr/cs257/archive/simon-peyton-jones/multicore-ghc.pdf Runtime Support for Multicore Haskell] (page 2 of 12).</small>
  +
</blockquote>
  +
   
 
Instead of two or more similar primitives with similar purposes, extend the existing <code>seq</code> primitive with the traditional ordering of evaluation for its parameters - first, then second; with the role of simple strictness-control being performed by a new primitive with a more appropriate name e.g.
 
Instead of two or more similar primitives with similar purposes, extend the existing <code>seq</code> primitive with the traditional ordering of evaluation for its parameters - first, then second; with the role of simple strictness-control being performed by a new primitive with a more appropriate name e.g.

Latest revision as of 05:28, 17 September 2024

The seq primitive, despite its name, is not required to evaluate its parameters in some predefined order, according to the Haskell 2010 Report. For parallel programming, sometimes a variant of seq is needed with such an ordering:


The seq combinator implements sequential composition. When the expression e1 ‘seq‘ e2 is evaluated, e1 is evaluated to weak head normal form first, and then the value of e2 is returned. In the following parallel nfib function, seq is used to force the evaluation of n2 before the addition takes place. This is because Haskell does not specify which operand is evaluated first, and if n1 was evaluated before n2, there would be no parallelism.

nfib :: Int -> Int
nfib n | n <= 1    = 1
       | otherwise = n1 par (n2 seq n1 + n2 + 1)
                     where
                       n1 = nfib (n-1)
                       n2 = nfib (n-2)
Accidents always Come in Threes: A Case Study of Data-intensive Programs in Parallel Haskell (page 2 of 14).


2.1 The need forpseq

The pseq combinator is used for sequencing; informally, it evaluates its first argument to weak-head normal form, and then evaluates its second argument, returning the value of its second argument. Consider this definition of parMap:

parMap f []     = []
parMap f (x:xs) = y par (ys pseq y:ys)
   where y  = f x
         ys = parMap f xs

The intention here is to spark the evaluation of f x, and then evaluate parMap f xs, before returning the new list y:ys. The programmer is hoping to express an ordering of the evaluation: first spark y, then evaluate ys.

Runtime Support for Multicore Haskell (page 2 of 12).


Instead of two or more similar primitives with similar purposes, extend the existing seq primitive with the traditional ordering of evaluation for its parameters - first, then second; with the role of simple strictness-control being performed by a new primitive with a more appropriate name e.g. amid, in Strictness without ordering, or confusion.

Atravers 02:00, 7 January 2019 (UTC)