[85] | 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 |
---|
[123] | 66 | node = pypar.get_processor_name() |
---|
[85] | 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 | |
---|
[123] | 105 | pypar.finalize() |
---|
[85] | 106 | |
---|
| 107 | |
---|