Parallelisation and Java


The algorithm we'll work to is:

  1. Make an local array containing the densities in the landscape on a particular node
  2. Send the local array to node zero
  3. Receive all the local arrays on node zero
  4. Add them up on node zero to make a global density array
  5. Send the global array to all the other nodes from node zero
  6. Receive the global density array back from node zero
  7. Move if necessary

Let's start with making the local array in Model.java - remember, each node gets its own copy of Model.java, Agent.java, and Landscape.java. This Model.java variable is going to contain the densities for the local node. It will then be sent to node zero to be added to the total for all nodes:

// Run
 
int[] densities = null;
 
for (int time = 0; time < iterations; time++) {
 
   if (node != 0) {
 
      landscape.calcDensities();
 
      densities = landscape.getDensities();
 

The last line requires we add a getDensities method in Landscape.java to return the array made by landscape.calcDensities. While we're at it, we might as well also add a setDensities method, as we'll need it later (here's the code: Landscape.java). Next, back in Model.java, we send the returned array to node zero.

      try {
 
         MPI.COMM_WORLD.Send
            (densities, 0, width * height, MPI.INT, 0, 50);
 
      } catch (MPIException mpiE) {
 
         mpiE.printStackTrace();
 
      }
 
   }
// End of if not node zero loop from above.
 
   for (int i = 0; i < numberOfAgents; i++) {
 
      agents[i].step();
 
   }
 
} // End of time iterations loop from above.
 

The agents[i].step() loops want to go after we've sorted out the densities - so we'll move them again in a second. You can find the docs for the send method here. The final "50" is a message tag - an arbitary number that is used to check the message sent is received by the right code (the receiving statement has the same number).


Next we need to write the receiving code for node zero, so we replace the end of the "if not node zero" statement with...

   } else { // if node is node zero
 
      densities = new int [width*height];
 
      for (int i = 1; i < numberOfNodes; i++) {
 
         
// Get the local density from each node i.
 
         int[] localDensities = int [width*height];
 
         try {
 
           MPI.COMM_WORLD.Recv
           (localDensities, 0, width * height, MPI.INT, i, 50);
 
         } catch (MPIException mpiE) {
 
            mpiE.printStackTrace();
 
         }
 
         
// Add node i's density surface to the global surface.
 
         for (int x = 0; x < width; x++) {
 
            for (int y = 0; y < height; y++) {
 
              densities[(y*width) + x] =
             densities[(y*width)+x]+localDensities[(y*width)+x];
 
            }
 
         }
 
      }
// End of looping through nodes.
 
   } // End of if not node zero loop from above.
 
   for (int i = 0; i < numberOfAgents; i++) {
 
      agents[i].step();
 
   }
 
} // End of time iterations loop from above.
 

Again, we've shifted the agents[i].step() loops down. You can find details of the recv method here. Now that's done, let's have a look at our Model.java class with the alterations in.

So the final thing is to pass the global density array back again. We'll do that Next.