Parallelisation and Java
The algorithm we'll work to is:
- Make an local array containing the densities in the landscape on a particular node
- Send the local array to node zero
- Receive all the local arrays on node zero
- Add them up on node zero to make a global density array
- Send the global array to all the other nodes from node zero
- Receive the global density array back from node zero
- 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.