1.1 --- a/README.txt Sun May 17 23:29:54 2009 +0200
1.2 +++ b/README.txt Thu May 21 19:24:06 2009 +0200
1.3 @@ -42,11 +42,13 @@
1.4 simple_managed_queue Yes Yes Yes
1.5 simple_managed Yes Yes Yes
1.6 simple_pmap Yes
1.7 +simple_pmap_iter Yes
1.8 simple_start_queue Yes Yes Yes
1.9 simple_start Yes Yes
1.10
1.11 -The simplest parallel program is simple_pmap.py which employs the pmap
1.12 -function resembling the built-in map function in Python.
1.13 +The simplest parallel programs are simple_pmap.py and simple_pmap_iter.py
1.14 +which employ the pmap function resembling the built-in map function in
1.15 +Python.
1.16
1.17 Other simple programs are those employing the Queue class, together with those
1.18 using the manage method which associates functions or callables with Queue or
1.19 @@ -143,13 +145,18 @@
1.20 ------------
1.21
1.22 This software depends on standard library features which are stated as being
1.23 -available only on "UNIX"; it has only been tested on a GNU/Linux system.
1.24 +available only on "UNIX"; it has only been tested repeatedly on a GNU/Linux
1.25 +system, and occasionally on systems running OpenSolaris.
1.26
1.27 New in pprocess 0.4.1 (Changes since pprocess 0.4)
1.28 --------------------------------------------------
1.29
1.30 * Fixed the get_number_of_cores function to work with /proc/cpuinfo where
1.31 the "physical id" field is missing.
1.32 + * Changed the Map class to permit incremental access to received results
1.33 + from completed parts of the sequence of inputs, also adding an iteration
1.34 + interface.
1.35 + * Added an example, simple_pmap_iter.py, to demonstrate iteration over maps.
1.36
1.37 New in pprocess 0.4 (Changes since pprocess 0.3.1)
1.38 --------------------------------------------------
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/examples/simple_pmap_iter.py Thu May 21 19:24:06 2009 +0200
2.3 @@ -0,0 +1,54 @@
2.4 +#!/usr/bin/env python
2.5 +
2.6 +"""
2.7 +A simple example of parallel computation using map-style processing.
2.8 +"""
2.9 +
2.10 +import pprocess
2.11 +import time
2.12 +#import random
2.13 +
2.14 +# Array size and a limit on the number of processes.
2.15 +
2.16 +N = 10
2.17 +limit = 10
2.18 +delay = 1
2.19 +
2.20 +# Work function.
2.21 +
2.22 +def calculate(t):
2.23 +
2.24 + "A supposedly time-consuming calculation on 't'."
2.25 +
2.26 + i, j = t
2.27 + #time.sleep(delay * random.random())
2.28 + time.sleep(delay)
2.29 + return i * N + j
2.30 +
2.31 +# Main program.
2.32 +
2.33 +if __name__ == "__main__":
2.34 +
2.35 + t = time.time()
2.36 +
2.37 + # Initialise an array.
2.38 +
2.39 + sequence = []
2.40 + for i in range(0, N):
2.41 + for j in range(0, N):
2.42 + sequence.append((i, j))
2.43 +
2.44 + # Perform the work.
2.45 +
2.46 + results = pprocess.pmap(calculate, sequence, limit=limit)
2.47 +
2.48 + # Show the results.
2.49 +
2.50 + for i, result in enumerate(results):
2.51 + print result,
2.52 + if i % N == N - 1:
2.53 + print
2.54 +
2.55 + print "Time taken:", time.time() - t
2.56 +
2.57 +# vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/packages/ubuntu-feisty/python-pprocess/debian/changelog Sun May 17 23:29:54 2009 +0200
3.2 +++ b/packages/ubuntu-feisty/python-pprocess/debian/changelog Thu May 21 19:24:06 2009 +0200
3.3 @@ -2,8 +2,13 @@
3.4
3.5 * Fixed the get_number_of_cores function to work with
3.6 /proc/cpuinfo where the "physical id" field is missing.
3.7 + * Changed the Map class to permit incremental access to
3.8 + received results from completed parts of the sequence of
3.9 + inputs, also adding an iteration interface.
3.10 + * Added an example, simple_pmap_iter.py, to demonstrate
3.11 + iteration over maps.
3.12
3.13 - -- Paul Boddie <paul@boddie.org.uk> Sun, 17 May 2009 23:28:27 +0200
3.14 + -- Paul Boddie <paul@boddie.org.uk> Thu, 21 May 2009 19:13:47 +0200
3.15
3.16 pprocess (0.4-0ubuntu1) feisty; urgency=low
3.17
4.1 --- a/packages/ubuntu-hoary/python2.4-parallel-pprocess/debian/changelog Sun May 17 23:29:54 2009 +0200
4.2 +++ b/packages/ubuntu-hoary/python2.4-parallel-pprocess/debian/changelog Thu May 21 19:24:06 2009 +0200
4.3 @@ -2,8 +2,13 @@
4.4
4.5 * Fixed the get_number_of_cores function to work with
4.6 /proc/cpuinfo where the "physical id" field is missing.
4.7 + * Changed the Map class to permit incremental access to
4.8 + received results from completed parts of the sequence of
4.9 + inputs, also adding an iteration interface.
4.10 + * Added an example, simple_pmap_iter.py, to demonstrate
4.11 + iteration over maps.
4.12
4.13 - -- Paul Boddie <paul@boddie.org.uk> Sun, 17 May 2009 23:28:59 +0200
4.14 + -- Paul Boddie <paul@boddie.org.uk> Thu, 21 May 2009 19:13:32 +0200
4.15
4.16 parallel-pprocess (0.4-0ubuntu1) hoary; urgency=low
4.17
5.1 --- a/pprocess.py Sun May 17 23:29:54 2009 +0200
5.2 +++ b/pprocess.py Thu May 21 19:24:06 2009 +0200
5.3 @@ -38,6 +38,10 @@
5.4 except NameError:
5.5 from sets import Set as set
5.6
5.7 +# Special values.
5.8 +
5.9 +class Undefined: pass
5.10 +
5.11 # Communications.
5.12
5.13 class AcknowledgementError(Exception):
5.14 @@ -631,6 +635,7 @@
5.15 self.channel_number = 0
5.16 self.channels = {}
5.17 self.results = []
5.18 + self.current_index = 0
5.19
5.20 def add(self, channel):
5.21
5.22 @@ -648,7 +653,7 @@
5.23 process and the created process.
5.24 """
5.25
5.26 - self.results.append(None) # placeholder
5.27 + self.results.append(Undefined) # placeholder
5.28 Exchange.start(self, callable, *args, **kw)
5.29
5.30 def create(self):
5.31 @@ -660,7 +665,7 @@
5.32 this exchange.
5.33 """
5.34
5.35 - self.results.append(None) # placeholder
5.36 + self.results.append(Undefined) # placeholder
5.37 return Exchange.create(self)
5.38
5.39 def __call__(self, callable, sequence):
5.40 @@ -683,14 +688,6 @@
5.41
5.42 return self
5.43
5.44 - def __getitem__(self, i):
5.45 - self.finish()
5.46 - return self.results[i]
5.47 -
5.48 - def __iter__(self):
5.49 - self.finish()
5.50 - return iter(self.results)
5.51 -
5.52 def store_data(self, channel):
5.53
5.54 "Accumulate the incoming data, associating results with channels."
5.55 @@ -699,6 +696,58 @@
5.56 self.results[self.channels[channel]] = data
5.57 del self.channels[channel]
5.58
5.59 + def __iter__(self):
5.60 + return self
5.61 +
5.62 + def next(self):
5.63 +
5.64 + "Return the next element in the map."
5.65 +
5.66 + try:
5.67 + return self._next()
5.68 + except IndexError:
5.69 + pass
5.70 +
5.71 + while self.active():
5.72 + self.store()
5.73 + try:
5.74 + return self._next()
5.75 + except IndexError:
5.76 + pass
5.77 + else:
5.78 + raise StopIteration
5.79 +
5.80 + def __getitem__(self, i):
5.81 +
5.82 + "Return element 'i' from the map."
5.83 +
5.84 + try:
5.85 + return self._get(i)
5.86 + except IndexError:
5.87 + pass
5.88 +
5.89 + while self.active():
5.90 + self.store()
5.91 + try:
5.92 + return self._get(i)
5.93 + except IndexError:
5.94 + pass
5.95 + else:
5.96 + raise IndexError, i
5.97 +
5.98 + # Helper methods for the above access methods.
5.99 +
5.100 + def _next(self):
5.101 + result = self._get(self.current_index)
5.102 + self.current_index += 1
5.103 + return result
5.104 +
5.105 + def _get(self, i):
5.106 + result = self.results[i]
5.107 + if result is Undefined or isinstance(i, slice) and Undefined in result:
5.108 + raise IndexError, i
5.109 + return result
5.110 +
5.111 class Queue(Exchange):
5.112
5.113 """