dad5287b74c56892ae85b7a01fed926c9c31ef95
[ghc-base.git] / Control / Parallel / Strategies.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module      :  Control.Parallel.Strategies
4 -- Copyright   :  (c) The University of Glasgow 2001
5 -- License     :  BSD-style (see the file libraries/base/LICENSE)
6 -- 
7 -- Maintainer  :  libraries@haskell.org
8 -- Stability   :  experimental
9 -- Portability :  non-portable
10 --
11 -- Parallel strategy combinators. See
12 -- <http://www.macs.hw.ac.uk/~dsg/gph/papers/html/Strategies/strategies.html>
13 -- for more information.
14 --
15 -- Original authors:
16 --      Phil Trinder, Hans-Wolfgang Loidl, Kevin Hammond et al. 
17 --
18 -----------------------------------------------------------------------------
19 module Control.Parallel.Strategies (
20    -- * Strategy Type, Application and Semantics
21    Done, Strategy,
22    (>|), (>||),
23    using, demanding, sparking,
24    -- * Basic Strategies                                     
25    r0, rwhnf, NFData(..),
26    -- * Strategic Function Application
27    ($|), ($||),
28    (.|), (.||),
29    (-|), (-||),
30    -- * Tuples
31    seqPair, parPair,
32    seqTriple, parTriple,
33    -- * Lists: Parallel Strategies
34    parList, parListN, parListNth, parListChunk, 
35    parMap, parFlatMap, parZipWith,
36    -- * Lists: Sequential Strategies
37    seqList, seqListN, seqListNth, parBuffer,
38    -- * Arrays
39    seqArr, parArr,
40    -- * Deprecated types and functions
41    sPar, sSeq,
42    Assoc(..),
43    fstPairFstList, force, sforce
44   ) where
45
46 -- based on hslibs/concurrent/Strategies.lhs; see it for more detailed
47 -- code comments. 
48
49 import Control.Parallel as Parallel (par, pseq)
50 import Data.Array
51 import Data.Complex
52 import Data.Int
53 import qualified Data.IntMap (IntMap, toList)
54 import qualified Data.IntSet (IntSet, toList)
55 import qualified Data.Map (Map, toList)
56 import qualified Data.Set (Set, toList)
57 import qualified Data.Tree (Tree(..))
58 import Data.Word
59
60 import Prelude hiding (seq)
61 import qualified Prelude (seq)
62
63 -- not a terribly portable way of getting at Ratio rep.
64 #ifdef __GLASGOW_HASKELL__
65 import GHC.Real (Ratio(..))     -- The basic defns for Ratio
66 #endif
67
68 #ifdef __HUGS__
69 import Hugs.Prelude(Ratio(..) )
70 #endif
71
72 #ifdef __NHC__
73 import Ratio (Ratio(..) )
74 #endif
75
76 infixl 0 `using`,`demanding`,`sparking`              -- weakest precedence!
77
78 infixr 2 >||                -- another name for par
79 infixr 3 >|                 -- another name for seq
80 infixl 6 $||, $|            -- strategic function application (seq and par)
81 infixl 9 .|, .||, -|, -||   -- strategic (inverse) function composition
82
83 -- We need 'pseq', not the Prelude 'seq' here.  See the documentation
84 -- with 'pseq' in Control.Parallel.
85 seq = Parallel.pseq
86
87 ------------------------------------------------------------------------------
88 -- *                    Strategy Type, Application and Semantics              
89 ------------------------------------------------------------------------------
90
91 {-
92 The basic combinators for strategies are 'par' and 'seq' but with types that 
93 indicate that they only combine the results of a strategy application. 
94
95 NB: This version can be used with Haskell 1.4 (GHC 2.05 and beyond), *but*
96     you won't get strategy checking on seq (only on par)!
97
98 The operators >| and >|| are alternative names for `seq` and `par`.
99 With the introduction of a Prelude function `seq` separating the Prelude 
100 function from the Strategy function becomes a pain. The notation also matches
101 the notation for strategic function application.
102 -}
103
104 type Done = ()
105
106 -- | A strategy takes a value and returns a 'Done' value to indicate that
107 --   the specifed evaluation has been performed.
108 type Strategy a = a -> Done
109
110
111 -- | Evaluates the first argument before the second.
112 (>|) :: Done -> Done -> Done 
113 {-# INLINE (>|) #-}
114 (>|) = Prelude.seq
115
116 -- | Evaluates the first argument in parallel with the second.
117 (>||) :: Done -> Done -> Done 
118 {-# INLINE (>||) #-}
119 (>||) = Parallel.par
120
121
122 -- | Takes a value and a strategy, and applies the strategy to the
123 -- value before returning the value. Used to express data-oriented 
124 -- parallelism. @x \`using\` s@ is a projection on @x@, i.e. both:
125 --
126 -- [a retraction] @x \`using\` s@ &#x2291; @x@
127 --
128 -- [idempotent] @(x \`using\` s) \`using\` s@ = @x \`using\` s@
129 --
130 using :: a -> Strategy a -> a
131 using x s = s x `seq` x
132
133
134 -- | Evaluates the second argument before the first.
135 -- Used to express control-oriented parallelism. The second
136 -- argument is usually a strategy application.
137 demanding :: a -> Done -> a
138 demanding = flip seq
139
140
141 -- | Evaluates the second argument in parallel with the first.
142 -- Used to express control-oriented
143 -- parallelism. The second argument is usually a strategy application.
144 sparking :: a -> Done -> a
145 sparking  = flip Parallel.par
146 -- Sparking should only be used
147 -- with a singleton sequence as it is not necessarily executed.
148
149 -- | A strategy corresponding to 'par': 
150 -- @x \`par\` e@ = @e \`using\` sPar x@.
151 --
152 -- 'sPar' has been superceded by 'sparking'.
153 -- Replace @e \`using\` sPar x@ with @e \`sparking\` rwhnf x@.
154 {-# DEPRECATED sPar "Use sparking instead." #-}
155 sPar :: a -> Strategy b
156 sPar x y = x `par` ()
157
158 -- | A strategy corresponding to 'seq': 
159 -- @x \`seq\` e@ = @e \`using\` sSeq x@.
160 --
161 -- 'sSeq' has been superceded by 'demanding'. 
162 -- Replace @e \`using\` sSeq x@ with @e \`demanding\` rwhnf x@.
163 {-# DEPRECATED sSeq "Use demanding instead." #-}
164 sSeq :: a -> Strategy b
165 sSeq x y = x `seq` ()
166
167 -----------------------------------------------------------------------------
168 -- *                    Basic Strategies                                     
169 -----------------------------------------------------------------------------
170
171 -- | Performs /no/ evaluation of its argument.
172 r0 :: Strategy a 
173 r0 x = ()
174
175 -- | Reduces its argument to weak head normal form.
176 rwhnf :: Strategy a 
177 rwhnf x = x `seq` ()  
178
179 class NFData a where
180   -- | Reduces its argument to (head) normal form.
181   rnf :: Strategy a
182   -- Default method. Useful for base types. A specific method is necessay for
183   -- constructed types
184   rnf = rwhnf
185
186 class (NFData a, Integral a) => NFDataIntegral a
187 class (NFData a, Ord a) => NFDataOrd a
188
189 ------------------------------------------------------------------------------
190 -- *                     Strategic Function Application
191 ------------------------------------------------------------------------------
192
193 {-
194 These are very
195 handy when writing pipeline parallelism asa sequence of @$@, @$|@ and
196 @$||@'s. There is no need of naming intermediate values in this case. The
197 separation of algorithm from strategy is achieved by allowing strategies
198 only as second arguments to @$|@ and @$||@.
199 -}
200
201 -- | Sequential function application. The argument is evaluated using
202 --   the given strategy before it is given to the function.
203 ($|) :: (a -> b) -> Strategy a -> a -> b
204 f $| s  = \ x -> f x `demanding` s x
205
206 -- | Parallel function application. The argument is evaluated using
207 -- the given strategy, in parallel with the function application.
208 ($||) :: (a -> b) -> Strategy a -> a -> b
209 f $|| s = \ x -> f x `sparking` s x
210
211 -- | Sequential function composition. The result of
212 -- the second function is evaluated using the given strategy, 
213 -- and then given to the first function.
214 (.|) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
215 (.|) f s g = \ x -> let  gx = g x 
216                     in   f gx `demanding` s gx
217
218 -- | Parallel function composition. The result of the second
219 -- function is evaluated using the given strategy,
220 -- in parallel with the application of the first function.
221 (.||) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
222 (.||) f s g = \ x -> let  gx = g x 
223                      in   f gx `sparking` s gx
224
225 -- | Sequential inverse function composition, 
226 -- for those who read their programs from left to right.
227 -- The result of the first function is evaluated using the 
228 -- given strategy, and then given to the second function.
229 (-|) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
230 (-|) f s g = \ x -> let  fx = f x 
231                     in   g fx `demanding` s fx
232
233 -- | Parallel inverse function composition,
234 -- for those who read their programs from left to right.
235 -- The result of the first function is evaluated using the 
236 -- given strategy, in parallel with the application of the 
237 -- second function.
238 (-||) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
239 (-||) f s g = \ x -> let  fx = f x 
240                      in   g fx `sparking` s fx 
241
242 ------------------------------------------------------------------------------
243 --                      Marking a Strategy
244 ------------------------------------------------------------------------------
245
246 {-
247 Marking a strategy.
248
249 Actually, @markStrat@  sticks a label @n@  into the sparkname  field of the
250 thread executing strategy @s@. Together with a runtime-system that supports
251 propagation of sparknames to the children this means that this strategy and
252 all its children have  the sparkname @n@ (if the  static sparkname field in
253 the @parGlobal@ annotation contains the value 1). Note, that the @SN@ field
254 of starting the marked strategy itself contains the sparkname of the parent
255 thread. The END event contains @n@ as sparkname.
256 -}
257
258 #if 0
259 markStrat :: Int -> Strategy a -> Strategy a 
260 markStrat n s x = unsafePerformPrimIO (
261      _casm_ ``%r = set_sparkname(CurrentTSO, %0);'' n `thenPrimIO` \ z ->
262      returnPrimIO (s x))
263 #endif
264
265 -----------------------------------------------------------------------------
266 --                      Strategy Instances and Functions                     
267 -----------------------------------------------------------------------------
268
269 -----------------------------------------------------------------------------
270 -- *                    Tuples
271 -----------------------------------------------------------------------------
272
273 {-
274 We currently support up to 9-tuples. If you need longer tuples you have to 
275 add the instance explicitly to your program.
276 -}
277
278 instance (NFData a, NFData b) => NFData (a,b) where
279   rnf (x,y) = rnf x `seq` rnf y
280
281 instance (NFData a, NFData b, NFData c) => NFData (a,b,c) where
282   rnf (x,y,z) = rnf x `seq` rnf y `seq` rnf z 
283
284 instance (NFData a, NFData b, NFData c, NFData d) => NFData (a,b,c,d) where
285   rnf (x1,x2,x3,x4) = rnf x1 `seq` 
286                         rnf x2 `seq` 
287                         rnf x3 `seq` 
288                         rnf x4 
289
290 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => 
291          NFData (a1, a2, a3, a4, a5) where
292   rnf (x1, x2, x3, x4, x5) =
293                   rnf x1 `seq`
294                   rnf x2 `seq`
295                   rnf x3 `seq`
296                   rnf x4 `seq`
297                   rnf x5
298
299 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => 
300          NFData (a1, a2, a3, a4, a5, a6) where
301   rnf (x1, x2, x3, x4, x5, x6) =
302                   rnf x1 `seq`
303                   rnf x2 `seq`
304                   rnf x3 `seq`
305                   rnf x4 `seq`
306                   rnf x5 `seq`
307                   rnf x6
308
309 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => 
310          NFData (a1, a2, a3, a4, a5, a6, a7) where
311   rnf (x1, x2, x3, x4, x5, x6, x7) =
312                   rnf x1 `seq`
313                   rnf x2 `seq`
314                   rnf x3 `seq`
315                   rnf x4 `seq`
316                   rnf x5 `seq`
317                   rnf x6 `seq`
318                   rnf x7
319
320 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) => 
321          NFData (a1, a2, a3, a4, a5, a6, a7, a8) where
322   rnf (x1, x2, x3, x4, x5, x6, x7, x8) =
323                   rnf x1 `seq`
324                   rnf x2 `seq`
325                   rnf x3 `seq`
326                   rnf x4 `seq`
327                   rnf x5 `seq`
328                   rnf x6 `seq`
329                   rnf x7 `seq`
330                   rnf x8
331
332 instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) => 
333          NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
334   rnf (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
335                   rnf x1 `seq`
336                   rnf x2 `seq`
337                   rnf x3 `seq`
338                   rnf x4 `seq`
339                   rnf x5 `seq`
340                   rnf x6 `seq`
341                   rnf x7 `seq`
342                   rnf x8 `seq`
343                   rnf x9
344
345 -- | Apply two strategies to the elements of a pair sequentially
346 --   from left to right.
347 seqPair :: Strategy a -> Strategy b -> Strategy (a,b)
348 seqPair strata stratb (x,y) = strata x `seq` stratb y 
349
350 -- | Apply two strategies to the elements of a pair in parallel.
351 parPair :: Strategy a -> Strategy b -> Strategy (a,b)
352 parPair strata stratb (x,y) = strata x `par` stratb y `par` ()
353 -- The reason for the last 'par' is so that the strategy terminates 
354 -- quickly. This is important if the strategy is used as the 1st 
355 -- argument of a seq
356
357 -- | Apply three strategies to the elements of a triple in sequentially
358 --   from left to right.
359 seqTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
360 seqTriple strata stratb stratc p@(x,y,z) = 
361   strata x `seq` 
362   stratb y `seq`
363   stratc z 
364
365 -- | Apply three strategies to the elements of a triple in parallel.
366 parTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
367 parTriple strata stratb stratc (x,y,z) = 
368   strata x `par` 
369   stratb y `par` 
370   stratc z `par`
371   ()
372
373 -----------------------------------------------------------------------------
374 --                      Atomic types
375 -----------------------------------------------------------------------------
376
377 {-
378 Weak head normal form and normal form are identical for integers, so the 
379 default rnf is sufficient. 
380 -}
381 instance NFData Int 
382 instance NFData Integer
383 instance NFData Float
384 instance NFData Double
385
386 instance NFData Int8
387 instance NFData Int16
388 instance NFData Int32
389 instance NFData Int64
390
391 instance NFData Word8
392 instance NFData Word16
393 instance NFData Word32
394 instance NFData Word64
395
396 instance NFDataIntegral Int
397 instance NFDataOrd Int
398
399 --Rational and complex numbers.
400
401 instance (Integral a, NFData a) => NFData (Ratio a) where
402   rnf (x:%y) = rnf x `seq` 
403                rnf y `seq`
404                ()
405
406 instance (RealFloat a, NFData a) => NFData (Complex a) where
407   rnf (x:+y) = rnf x `seq` 
408                  rnf y `seq`
409                ()
410
411 instance NFData Char
412 instance NFData Bool
413 instance NFData ()
414
415 -----------------------------------------------------------------------------
416 --                      Various library types                                               
417 -----------------------------------------------------------------------------
418
419 instance NFData a => NFData (Maybe a) where
420     rnf Nothing  = ()
421     rnf (Just x) = rnf x
422
423 instance (NFData a, NFData b) => NFData (Either a b) where
424     rnf (Left x)  = rnf x
425     rnf (Right y) = rnf y
426
427 instance (NFData k, NFData a) => NFData (Data.Map.Map k a) where
428     rnf = rnf . Data.Map.toList
429
430 instance NFData a => NFData (Data.Set.Set a) where
431     rnf = rnf . Data.Set.toList
432
433 instance NFData a => NFData (Data.Tree.Tree a) where
434     rnf (Data.Tree.Node r f) = rnf r `seq` rnf f
435
436 instance NFData a => NFData (Data.IntMap.IntMap a) where
437     rnf = rnf . Data.IntMap.toList
438
439 instance NFData Data.IntSet.IntSet where
440     rnf = rnf . Data.IntSet.toList
441
442 -----------------------------------------------------------------------------
443 --                      Lists                                               
444 -----------------------------------------------------------------------------
445
446 instance NFData a => NFData [a] where
447   rnf [] = ()
448   rnf (x:xs) = rnf x `seq` rnf xs
449
450 ----------------------------------------------------------------------------
451 -- *                   Lists: Parallel Strategies
452 ----------------------------------------------------------------------------
453
454 -- | Applies a strategy to every element of a list in parallel.
455 parList :: Strategy a -> Strategy [a]
456 parList strat []     = ()
457 parList strat (x:xs) = strat x `par` (parList strat xs)
458
459 -- | Applies a strategy to the first @n@ elements of a list in parallel.
460 parListN :: (Integral b) => b -> Strategy a -> Strategy [a]
461 parListN n strat []     = ()
462 parListN 0 strat xs     = ()
463 parListN n strat (x:xs) = strat x `par` (parListN (n-1) strat xs)
464
465 -- | Evaluates @n@ elements of the spine of the argument list and applies
466 -- the given strategy to the @n@th element (if there is one) in parallel with
467 -- the result. E.g. @parListNth 2 [e1, e2, e3]@ evaluates @e3@.
468 parListNth :: Int -> Strategy a -> Strategy [a]
469 parListNth n strat xs 
470   | null rest = ()
471   | otherwise = strat (head rest) `par` ()
472   where
473     rest = drop n xs
474
475 -- | Splits a list into chunks (sub-sequences) of length @n@,
476 -- and applies a strategy sequentially to the elements in each
477 -- chunk. The chunks are evaluated in parallel.
478 -- This is useful for increasing the grain size.
479 parListChunk :: Int -> Strategy a -> Strategy [a]
480 parListChunk n strat [] = ()
481 parListChunk n strat xs = seqListN n strat xs `par` 
482                             parListChunk n strat (drop n xs)
483
484 -- | Applies a function to each element of a list and 
485 -- and evaluates the result list in parallel,
486 -- using the given strategy for each element.
487 parMap :: Strategy b -> (a -> b) -> [a] -> [b]
488 parMap strat f xs = map f xs `using` parList strat
489
490 -- | Uses 'parMap' to apply a list-valued function to each
491 -- element of a list in parallel, and concatenates the results.
492 parFlatMap :: Strategy [b] -> (a -> [b]) -> [a] -> [b]
493 parFlatMap strat f xs = concat (parMap strat f xs)
494
495 -- | Zips together two lists using a function,
496 -- and evaluates the result list in parallel.
497 parZipWith :: Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]
498 parZipWith strat z as bs = 
499   zipWith z as bs `using` parList strat
500
501 ----------------------------------------------------------------------------
502 -- *                     Lists: Sequential Strategies
503 ----------------------------------------------------------------------------
504
505 -- | Sequentially applies a strategy to each element of a list.
506 seqList :: Strategy a -> Strategy [a]
507 seqList strat []     = ()
508 seqList strat (x:xs) = strat x `seq` (seqList strat xs)
509
510 -- | Sequentially applies a strategy to the first n elements of a list.
511 seqListN :: (Integral a) => a -> Strategy b -> Strategy [b]
512 seqListN n strat []     = ()
513 seqListN 0 strat xs     = ()
514 seqListN n strat (x:xs) = strat x `seq` (seqListN (n-1) strat xs)
515
516 -- | Applies a strategy to the @n@th element of a list
517 --  (if there is one) before returning the result. 
518 --  E.g. @seqListNth 2 [e1, e2, e3]@ evaluates @e3@.
519 seqListNth :: Int -> Strategy b -> Strategy [b]
520 seqListNth n strat xs 
521   | null rest = ()
522   | otherwise = strat (head rest) 
523   where
524     rest = drop n xs
525
526 -- | Parallel n-buffer function added for the revised version of the strategies
527 -- paper. 'parBuffer' supersedes the older @fringeList@. It has the same
528 -- semantics.
529 parBuffer :: Int -> Strategy a -> [a] -> [a]
530 parBuffer n s xs = 
531   return xs (start n xs)
532   where
533     return (x:xs) (y:ys) = (x:return xs ys) `sparking` s y
534     return xs     []     = xs
535
536     start n []     = []
537     start 0 ys     = ys
538     start n (y:ys) = start (n-1) ys `sparking` s y
539
540 {-
541  'fringeList' implements a `rolling buffer' of length n, i.e.applies a
542  strategy to the nth element of list when the head is demanded. More
543  precisely:
544
545    semantics:         fringeList n s = id :: [b] -> [b]
546    dynamic behaviour: evalutates the nth element of the list when the
547                       head is demanded.
548    
549  The idea is to provide a `rolling buffer' of length n.
550 fringeList :: (Integral a) => a -> Strategy b -> [b] -> [b]
551 fringeList n strat [] = []
552 fringeList n strat (r:rs) = 
553   seqListNth n strat rs `par`
554   r:fringeList n strat rs
555 -}
556
557 ------------------------------------------------------------------------------
558 -- *                    Arrays
559 ------------------------------------------------------------------------------
560 instance (Ix a, NFData a, NFData b) => NFData (Array a b) where
561   rnf x = rnf (bounds x) `seq` seqList rnf (elems x) `seq` ()
562
563 -- | Apply a strategy to all elements of an array sequentially.
564 seqArr :: (Ix b) => Strategy a -> Strategy (Array b a)
565 seqArr s arr = seqList s (elems arr)
566
567 -- | Apply a strategy to all elements of an array in parallel.
568 parArr :: (Ix b) => Strategy a -> Strategy (Array b a)
569 parArr s arr = parList s (elems arr)
570
571 {-# DEPRECATED Assoc "Does not belong in Control.Parallel.Strategies" #-}
572 data  Assoc a b =  a := b  deriving ()
573
574 instance (NFData a, NFData b) => NFData (Assoc a b) where
575   rnf (x := y) = rnf x `seq` rnf y `seq` ()
576
577 ------------------------------------------------------------------------------
578 -- *                    Some strategies specific for Lolita     
579 ------------------------------------------------------------------------------
580
581 {-# DEPRECATED fstPairFstList "This was just an example. Write your own." #-}
582 fstPairFstList :: (NFData a) => Strategy [(a,b)]
583 fstPairFstList = seqListN 1 (seqPair rwhnf r0)
584
585 -- Some HACKs for Lolita. AFAIK force is just another name for our rnf and
586 -- sforce is a shortcut (definition here is identical to the one in Force.lhs)
587
588 {-# DEPRECATED force, sforce "Lolita-specific hacks." #-}
589 force :: (NFData a) => a -> a 
590 sforce :: (NFData a) => a -> b -> b
591
592 force = id $| rnf
593 sforce x y = force x `seq` y