Download User Guide - Scientific Computing Associates

Transcript
Molecular Dynamics
Finish initialization.
return;
}
After performing the same initial setup steps as the sequential version, the parallel version
of nb_energy_setup places some global data in tuple space.
The majority of the code shown in this routine is concerned with dividing the work up
among the worker processes. The tasks created here define the range of the data each
worker is responsible for. This represents a somewhat different technique from the usual
master/worker scenario. In the latter, the work is divided into tasks which are
independent of any particular worker, and each worker grabs a task when it needs one.
Here, the total work is divided among the workers at the beginning of the calculation; the
work each worker does is essentially part of its structure—in this case, a function of its
worker ID number. This technique of dividing the problem space into discrete chunks
and assigning each to one worker is known as domain decomposition. The parameters
calculated here and communicated to each worker via tuple space will be used in both the
summing of special charges done in the setup phase (with results collected at the end of
this routine), and in the actual nonbonded interactions computation later in the program.
The scheme for dividing the work here is somewhat complex, but it is designed to ensure
good load balancing among the worker processes—this is always a concern when a
domain decomposition approach is taken.
For a molecular dynamics calculation, the total number of nonbonded interactions for an
N-atom molecule is approximately N*(N-1)/2, and so we want each worker to do about
(N*(N-1)/2) / num_workers
of them. If there are N atoms, there are N2 possible interactions, but we throw out pairs
where an atom is interacting with itself. The factor of 1/2 comes from the fact that the
interactions are symmetric (A’s effect on B is equivalent to B’s effect on A) and thus only
need to be computed once. We should also remove bonded pairs, but if this number is
small compared to the total number of interactions, then our formula is a reasonable
approximation to the ideal number of interactions per worker.
In some cases, the total work can just be divided as evenly as possible among the
workers. Here, we might like to just give each worker the number of interactions we
computed above, correcting the last worker’s amount for any remainder and other integer
rounding we had to do. However, the interaction pairs are actually stored as rows in a
lower triangular matrix (a matrix with all of its non-zero elements on or below the
diagonal), and for maximal efficiency, we want to give only complete rows of the matrix
to each worker. Given this constraint, it is necessary to figure out how many rows to give
each worker so that the number of elements each one gets comes out about the same
(and close to the target number).
To do so, the program uses the fact that there are I non-zero elements in row I of a lower
triangular matrix, and assigns consecutive rows to each successive workers until the
number of elements it has exceeds the target number, or until all the rows are gone. This
Linda User Guide
91