diff options
author | Araq <rumpf_a@web.de> | 2014-06-09 08:03:54 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-06-09 08:03:54 +0200 |
commit | 947b152163d04b4ac27697646a5200496573be13 (patch) | |
tree | c9050f4e9f46d6d7cb3756a4047dd8cad360f652 /doc/spawn.txt | |
parent | 4220b1c81d433e30e3d41c8ecb05b2a9edaface5 (diff) | |
download | Nim-947b152163d04b4ac27697646a5200496573be13.tar.gz |
some changes
Diffstat (limited to 'doc/spawn.txt')
-rw-r--r-- | doc/spawn.txt | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/doc/spawn.txt b/doc/spawn.txt index 19560ebf5..ed500f3a5 100644 --- a/doc/spawn.txt +++ b/doc/spawn.txt @@ -6,6 +6,8 @@ Nimrod has two flavors of parallelism: 1) `Structured`:idx parallelism via the ``parallel`` statement. 2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement. +Both need the `threadpool <threadpool.html>`_ module to work. + Somewhat confusingly, ``spawn`` is also used in the ``parallel`` statement with slightly different semantics. ``spawn`` always takes a call expression of the form ``f(a, ...)``. Let ``T`` be ``f``'s return type. If ``T`` is ``void`` @@ -20,6 +22,25 @@ the overhead of an indirection via ``FlowVar[T]`` to ensure correctness. Parallel statement ================== +Example: + +.. code-block:: nimrod + # Compute PI in an inefficient way + import strutils, math, threadpool + + proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1) + + proc pi(n: int): float = + var ch = newSeq[float](n+1) + parallel: + for k in 0..ch.high: + ch[k] = spawn term(float(k)) + for k in 0..ch.high: + result += ch[k] + + echo formatFloat(pi(5000)) + + The parallel statement is the preferred mechanism to introduce parallelism in a Nimrod program. A subset of the Nimrod language is valid within a ``parallel`` section. This subset is checked to be free of data races at @@ -30,17 +51,21 @@ The subset is in fact the full language with the following restrictions / changes: * ``spawn`` within a ``parallel`` section has special semantics. -* Every location of the form ``a[i]`` and ``a[i..j]`` and ``dest`` where +* Every location of the form ``a[i]`` and ``a[i..j]`` and ``dest`` where ``dest`` is part of the pattern ``dest = spawn f(...)`` has to be provable disjoint. This is called the *disjoint check*. -* Every other complex location ``loc`` that is used in a spawned - proc (``spawn f(loc)``) has to immutable for the duration of - the ``parallel``. This is called the *immutability check*. Currently it - is not specified what exactly "complex location" means. We need to make that - an optimization! -* Every array access has to be provable within bounds. +* Every other complex location ``loc`` that is used in a spawned + proc (``spawn f(loc)``) has to be immutable for the duration of + the ``parallel`` section. This is called the *immutability check*. Currently + it is not specified what exactly "complex location" means. We need to make + this an optimization! +* Every array access has to be provable within bounds. This is called + the *bounds check*. * Slices are optimized so that no copy is performed. This optimization is not - yet performed for ordinary slices outside of a ``parallel`` section. + yet performed for ordinary slices outside of a ``parallel`` section. Slices + are also special in that they currently do not support negative indexes! + + Spawn statement @@ -49,9 +74,25 @@ Spawn statement A standalone ``spawn`` statement is a simple construct. It executes the passed expression on the thread pool and returns a `data flow variable`:idx: ``FlowVar[T]`` that can be read from. The reading with the ``^`` operator is -**blocking**. However, one can use ``awaitAny`` to wait on multiple flow variables -at the same time. +**blocking**. However, one can use ``awaitAny`` to wait on multiple flow +variables at the same time: + +.. code-block:: nimrod + import threadpool, ... + + # wait until 2 out of 3 servers received the update: + proc main = + var responses = newSeq[RawFlowVar](3) + for i in 0..2: + responses[i] = spawn tellServer(Update, "key", "value") + var index = awaitAny(responses) + assert index >= 0 + responses.del(index) + discard awaitAny(responses) Like the ``parallel`` statement data flow variables ensure that no data races -are possible. +are possible. Due to technical limitations not every type ``T`` is possible in +a data flow variable: ``T`` has to be of the type ``ref``, ``string``, ``seq`` +or of a type that doesn't contain a type that is garbage collected. This +restriction will be removed in the future. |