[project @ 2000-01-24 16:47:24 by rrt]
[ghc-hetmet.git] / ghc / docs / users_guide / parallel.sgml
1 <Sect1 id="concurrent-and-parallel">
2 <Title>Concurrent and Parallel Haskell
3 </Title>
4
5 <Para>
6 <IndexTerm><Primary>Concurrent Haskell</Primary></IndexTerm>
7 <IndexTerm><Primary>Parallel Haskell</Primary></IndexTerm>
8 Concurrent and Parallel Haskell are Glasgow extensions to Haskell
9 which let you structure your program as a group of independent
10 `threads'.
11 </Para>
12
13 <Para>
14 Concurrent and Parallel Haskell have very different purposes.
15 </Para>
16
17 <Para>
18 Concurrent Haskell is for applications which have an inherent
19 structure of interacting, concurrent tasks (i.e. `threads').  Threads
20 in such programs may be <Emphasis>required</Emphasis>.  For example, if a concurrent thread has been spawned to handle a mouse click, it isn't
21 optional&mdash;the user wants something done!
22 </Para>
23
24 <Para>
25 A Concurrent Haskell program implies multiple `threads' running within
26 a single Unix process on a single processor.
27 </Para>
28
29 <Para>
30 You will find at least one paper about Concurrent Haskell hanging off
31 of <ULink URL="http://www.dcs.gla.ac.uk/~simonpj/">Simon Peyton Jones's Web page</ULink>.
32 </Para>
33
34 <Para>
35 Parallel Haskell is about <Emphasis>speed</Emphasis>&mdash;spawning threads onto multiple
36 processors so that your program will run faster.  The `threads'
37 are always <Emphasis>advisory</Emphasis>&mdash;if the runtime system thinks it can
38 get the job done more quickly by sequential execution, then fine.
39 </Para>
40
41 <Para>
42 A Parallel Haskell program implies multiple processes running on
43 multiple processors, under a PVM (Parallel Virtual Machine) framework.
44 </Para>
45
46 <Para>
47 Parallel Haskell is still relatively new; it is more about &ldquo;research
48 fun&rdquo; than about &ldquo;speed.&rdquo; That will change.
49 </Para>
50
51 <Para>
52 Again, check Simon's Web page for publications about Parallel Haskell
53 (including &ldquo;GUM&rdquo;, the key bits of the runtime system).
54 </Para>
55
56 <Para>
57 Some details about Parallel Haskell follow.  For more information
58 about concurrent Haskell, see the Concurrent section in the <ULink
59 URL="libs.html"
60 >GHC/Hugs Extension Libraries</ULink
61 > documentation.
62 </Para>
63
64 <Sect2>
65 <Title>Features specific to Parallel Haskell
66 <IndexTerm><Primary>Parallel Haskell&mdash;features</Primary></IndexTerm></Title>
67
68 <Sect3>
69 <Title>The <Literal>Parallel</Literal> interface (recommended)
70 <IndexTerm><Primary>Parallel interface</Primary></IndexTerm></Title>
71
72 <Para>
73 GHC provides two functions for controlling parallel execution, through
74 the <Literal>Parallel</Literal> interface:
75 </Para>
76
77 <Para>
78
79 <ProgramListing>
80 interface Parallel where
81 infixr 0 `par`
82 infixr 1 `seq`
83
84 par :: a -&#62; b -&#62; b
85 seq :: a -&#62; b -&#62; b
86 </ProgramListing>
87
88 </Para>
89
90 <Para>
91 The expression <Literal>(x `par` y)</Literal> <Emphasis>sparks</Emphasis> the evaluation of <Literal>x</Literal>
92 (to weak head normal form) and returns <Literal>y</Literal>.  Sparks are queued for
93 execution in FIFO order, but are not executed immediately.  At the
94 next heap allocation, the currently executing thread will yield
95 control to the scheduler, and the scheduler will start a new thread
96 (until reaching the active thread limit) for each spark which has not
97 already been evaluated to WHNF.
98 </Para>
99
100 <Para>
101 The expression <Literal>(x `seq` y)</Literal> evaluates <Literal>x</Literal> to weak head normal
102 form and then returns <Literal>y</Literal>.  The <Function>seq</Function> primitive can be used to
103 force evaluation of an expression beyond WHNF, or to impose a desired
104 execution sequence for the evaluation of an expression.
105 </Para>
106
107 <Para>
108 For example, consider the following parallel version of our old
109 nemesis, <Function>nfib</Function>:
110 </Para>
111
112 <Para>
113
114 <ProgramListing>
115 import Parallel
116
117 nfib :: Int -&#62; Int
118 nfib n | n &#60;= 1 = 1
119        | otherwise = par n1 (seq n2 (n1 + n2 + 1))
120                      where n1 = nfib (n-1)
121                            n2 = nfib (n-2)
122 </ProgramListing>
123
124 </Para>
125
126 <Para>
127 For values of <VarName>n</VarName> greater than 1, we use <Function>par</Function> to spark a thread
128 to evaluate <Literal>nfib (n-1)</Literal>, and then we use <Function>seq</Function> to force the
129 parent thread to evaluate <Literal>nfib (n-2)</Literal> before going on to add
130 together these two subexpressions.  In this divide-and-conquer
131 approach, we only spark a new thread for one branch of the computation
132 (leaving the parent to evaluate the other branch).  Also, we must use
133 <Function>seq</Function> to ensure that the parent will evaluate <VarName>n2</VarName> <Emphasis>before</Emphasis>
134 <VarName>n1</VarName> in the expression <Literal>(n1 + n2 + 1)</Literal>.  It is not sufficient to
135 reorder the expression as <Literal>(n2 + n1 + 1)</Literal>, because the compiler may
136 not generate code to evaluate the addends from left to right.
137 </Para>
138
139 </Sect3>
140
141 <Sect3>
142 <Title>Underlying functions and primitives
143 <IndexTerm><Primary>parallelism primitives</Primary></IndexTerm>
144 <IndexTerm><Primary>primitives for parallelism</Primary></IndexTerm></Title>
145
146 <Para>
147 The functions <Function>par</Function> and <Function>seq</Function> are wired into GHC, and unfold
148 into uses of the <Function>par&num;</Function> and <Function>seq&num;</Function> primitives, respectively.  If
149 you'd like to see this with your very own eyes, just run GHC with the
150 <Option>-ddump-simpl</Option> option.  (Anything for a good time&hellip;)
151 </Para>
152
153 </Sect3>
154
155 <Sect3>
156 <Title>Scheduling policy for concurrent/parallel threads
157 <IndexTerm><Primary>Scheduling&mdash;concurrent/parallel</Primary></IndexTerm>
158 <IndexTerm><Primary>Concurrent/parallel scheduling</Primary></IndexTerm></Title>
159
160 <Para>
161 Runnable threads are scheduled in round-robin fashion.  Context
162 switches are signalled by the generation of new sparks or by the
163 expiry of a virtual timer (the timer interval is configurable with the
164 <Option>-C[&lt;num&gt;]</Option><IndexTerm><Primary>-C&lt;num&gt; RTS option (concurrent,
165 parallel)</Primary></IndexTerm> RTS option).  However, a context switch doesn't
166 really happen until the current heap block is full.  You can't get any
167 faster context switching than this.
168 </Para>
169
170 <Para>
171 When a context switch occurs, pending sparks which have not already
172 been reduced to weak head normal form are turned into new threads.
173 However, there is a limit to the number of active threads (runnable or
174 blocked) which are allowed at any given time.  This limit can be
175 adjusted with the <Option>-t&lt;num&gt;</Option><IndexTerm><Primary>-t &lt;num&gt; RTS option (concurrent, parallel)</Primary></IndexTerm>
176 RTS option (the default is 32).  Once the
177 thread limit is reached, any remaining sparks are deferred until some
178 of the currently active threads are completed.
179 </Para>
180
181 </Sect3>
182
183 </Sect2>
184
185 </Sect1>