1 | #!/usr/bin/env python |
---|
2 | ######################################################### |
---|
3 | # |
---|
4 | # Example: Distributing work in parallel using pypar (MPI). |
---|
5 | # |
---|
6 | # Author: Ole Nielsen, ANU, March 2002. |
---|
7 | # |
---|
8 | ######################################################### |
---|
9 | # |
---|
10 | """Skeleton for using pypar to distribute work across processors. |
---|
11 | It is assumed that the function work knows how to perform different |
---|
12 | tasks (or the same task on different data) based on values of |
---|
13 | myid and numprocs. |
---|
14 | """ |
---|
15 | |
---|
16 | |
---|
17 | |
---|
18 | def work(myid, numprocs, data): |
---|
19 | """This simple example function that slices up the data |
---|
20 | based on values of numproc and myid. |
---|
21 | """ |
---|
22 | |
---|
23 | import Numeric |
---|
24 | |
---|
25 | # Identify local slice and process it |
---|
26 | # |
---|
27 | interval = len(data) |
---|
28 | myinterval = interval/numprocs |
---|
29 | |
---|
30 | mylower = myid*myinterval |
---|
31 | if myid == numprocs-1: |
---|
32 | myupper = interval+1 |
---|
33 | else: |
---|
34 | myupper = mylower + myinterval |
---|
35 | |
---|
36 | mydata = data[mylower:myupper] |
---|
37 | |
---|
38 | # Computation (average) |
---|
39 | # |
---|
40 | myavg = float(Numeric.sum(mydata))/len(mydata) |
---|
41 | print "P%d: %s Local avg=%.4f" %(myid, str(mydata), myavg) |
---|
42 | |
---|
43 | return myavg*len(mydata) |
---|
44 | |
---|
45 | |
---|
46 | |
---|
47 | |
---|
48 | ################################################### |
---|
49 | # Main program - communication takes place here |
---|
50 | # |
---|
51 | import pypar, Numeric |
---|
52 | |
---|
53 | |
---|
54 | # Get data. Here it is just generated but it could be read |
---|
55 | # from file or given as an input parameter. |
---|
56 | # |
---|
57 | lower = 100 |
---|
58 | upper = 121 |
---|
59 | data = Numeric.array(range(lower,upper)) |
---|
60 | |
---|
61 | # |
---|
62 | # Get parallel parameters |
---|
63 | # |
---|
64 | numprocs = pypar.size() # Number of processors |
---|
65 | myid = pypar.rank() # Id of this processor |
---|
66 | node = pypar.get_processor_name() |
---|
67 | |
---|
68 | print "I am proc %d of %d on node %s" %(myid, numprocs, node) |
---|
69 | |
---|
70 | |
---|
71 | |
---|
72 | # |
---|
73 | # Do work in parallel |
---|
74 | # |
---|
75 | x = work(myid, numprocs, data) #Do work on all processors |
---|
76 | print "Proc %d finished working" %myid |
---|
77 | |
---|
78 | # |
---|
79 | # Communication |
---|
80 | # |
---|
81 | if numprocs > 1: |
---|
82 | # |
---|
83 | # Processor 0 gathers all results and merge them |
---|
84 | # |
---|
85 | if myid == 0: |
---|
86 | for id in range(1,numprocs): |
---|
87 | print "P%d receving from P%d" %(0, id) |
---|
88 | x = x + pypar.receive(id) #Add up (would be more complex in general) |
---|
89 | |
---|
90 | # All other processors send their results back to processor 0 |
---|
91 | # |
---|
92 | else: |
---|
93 | print "P%d sending to P%d" %(myid, 0) |
---|
94 | pypar.send(x, 0) |
---|
95 | |
---|
96 | print "Proc %d after communication" %myid |
---|
97 | # |
---|
98 | # Compute overall average and report |
---|
99 | # |
---|
100 | |
---|
101 | if myid == 0: |
---|
102 | avg = x/len(data) |
---|
103 | print "Global average is %.4f" %avg |
---|
104 | |
---|
105 | pypar.finalize() |
---|
106 | |
---|
107 | |
---|