diff options
author | Thomas Radke <tradke@aei.mpg.de> | 2005-03-30 15:28:00 +0000 |
---|---|---|
committer | Thomas Radke <tradke@aei.mpg.de> | 2005-03-30 15:28:00 +0000 |
commit | 94daef6e66284e4bd9cd44cfe9f554932c7773c7 (patch) | |
tree | df80da062422e5363d871063b9154b3589d7f71b /Carpet/Carpet/src/Comm.cc | |
parent | b6ed81fe31a0a5571ea7433f1e2e2e93a630de16 (diff) |
CarpetLib, Carpet: implement and use collective communication buffers
Collective buffers are used to gather all components' data on a processor
before it gets send off to other processors in one go. This minimizes the
number of outstanding MPI communications down to O(N-1) and thus improves
overall efficiency as benchmarks show.
Each processor allocates a pair of single send/recv buffers to communicate
with all other processors. For this the class (actually, the struct) comm_state
was extended by 3 more states:
state_get_buffer_sizes: accumulates the sizes for the send/recv buffers
state_fill_send_buffers: gathers all the data into the send buffers
state_empty_recv_buffers: copies the data from the recv buffer back into
the processor's components
Send/recv buffers are exchanged during state_fill_send_buffers and
state_empty_recv_buffers. The constructor for a comm_state struct now takes
an argument <datatype> which denotes the CCTK datatype to use for the
attached collective buffers. If a negative value is passed here then it falls
back to using the old send/recv/wait communication scheme. The datatype
argument has a default value of -1 to maintain backwards compatibility to
existing code (which therefore will keep using the old scheme).
The new communication scheme is chosen by setting the parameter
CarpetLib::use_collective_communication_buffers to "yes". It defaults to "no"
meaning that the old send/recv/wait scheme is still used.
So far all the comm_state objects in the higher-level routines in thorn Carpet
(restriction/prolongation, regridding, synchronization) have been enabled to
use collective communication buffers.
Other thorns (CarpetInterp, CarpetIO*, CarpetSlab) will follow in separate
commits.
darcs-hash:20050330152811-776a0-51f426887fea099d1a67b42bd79e4f786979ba91.gz
Diffstat (limited to 'Carpet/Carpet/src/Comm.cc')
-rw-r--r-- | Carpet/Carpet/src/Comm.cc | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/Carpet/Carpet/src/Comm.cc b/Carpet/Carpet/src/Comm.cc index dd50e2140..c71458236 100644 --- a/Carpet/Carpet/src/Comm.cc +++ b/Carpet/Carpet/src/Comm.cc @@ -16,10 +16,12 @@ namespace Carpet { using namespace std; - static int CheckSyncGroupConsistency ( const cGH* cgh, - const char *groupname ); - static void ProlongateGroupBoundaries ( const cGH* cgh, - CCTK_REAL initial_time, int group ); + static int CheckSyncGroupConsistency (const cGH* cgh, + const char *groupname); + static void ProlongateGroupBoundaries (const cGH* cgh, + CCTK_REAL initial_time, int group, + int vartype); + int SyncGroup (const cGH* cgh, const char* groupname) { @@ -29,6 +31,8 @@ namespace Carpet { assert (group>=0 and group<CCTK_NumGroups()); assert (group<(int)arrdata.size()); const int grouptype = CCTK_GroupTypeI(group); + const int firstvar = CCTK_FirstVarIndexI (group); + const int vartype = CCTK_VarTypeI (firstvar); assert(grouptype == CCTK_GF || grouptype == CCTK_SCALAR || grouptype == CCTK_ARRAY); assert (CCTK_NumVarsInGroupI(group) != 0); @@ -43,18 +47,21 @@ namespace Carpet { if (do_prolongate && grouptype == CCTK_GF) { assert (reflevel>=0 and reflevel<reflevels); if (reflevel > 0) { - ProlongateGroupBoundaries ( cgh, cctk_initial_time, group ); + ProlongateGroupBoundaries (cgh, cctk_initial_time, group, vartype); } } // Sync - SyncGVGroup ( cgh, group ); + const vector<int> members(1, group); + group_set groups = {vartype, members}; + SyncGroups (cgh, groups); } return retval; } - void ProlongateGroupBoundaries ( const cGH* cgh, CCTK_REAL initial_time, - int group ) + static void ProlongateGroupBoundaries (const cGH* cgh, + CCTK_REAL initial_time, int group, + int vartype) { DECLARE_CCTK_PARAMETERS; @@ -62,26 +69,32 @@ namespace Carpet { const CCTK_REAL time = (cgh->cctk_time - initial_time) / delta_time; const int tl = 0; - // make the comm_state loop the innermost - // in order to minimise the number of outstanding communications - if (minimise_outstanding_communications) { - for (int m=0; m<(int)arrdata.at(group).size(); ++m) { - for (int var=0; var<CCTK_NumVarsInGroupI(group); ++var) { - for (int c=0; c<vhh.at(m)->components(reflevel); ++c) { - for (comm_state state; !state.done(); state.step()) { - arrdata.at(group).at(m).data.at(var)->ref_bnd_prolongate - (state, tl, reflevel, c, mglevel, time); + // Use collective or single-component buffers for communication ? + if (! use_collective_communication_buffers) { + vartype = -1; + } + + if (use_collective_communication_buffers || + ! minimise_outstanding_communications) { + for (comm_state state(vartype); ! state.done(); state.step()) { + for (int m = 0; m < arrdata.at(group).size(); ++m) { + for (int v = 0; v < arrdata.at(group).at(m).data.size(); ++v) { + ggf *const gv = arrdata.at(group).at(m).data.at(v); + for (int c = 0; c < vhh.at(m)->components(reflevel); ++c) { + gv->ref_bnd_prolongate (state, tl, reflevel, c, mglevel, time); } } } } } else { - for (comm_state state; !state.done(); state.step()) { - for (int m=0; m<(int)arrdata.at(group).size(); ++m) { - for (int var=0; var<CCTK_NumVarsInGroupI(group); ++var) { - for (int c=0; c<vhh.at(m)->components(reflevel); ++c) { - arrdata.at(group).at(m).data.at(var)->ref_bnd_prolongate - (state, tl, reflevel, c, mglevel, time); + // make the comm_state loop the innermost + // in order to minimise the number of outstanding communications + for (int m = 0; m < arrdata.at(group).size(); ++m) { + for (int v = 0; v < arrdata.at(group).at(m).data.size(); ++v) { + ggf *const gv = arrdata.at(group).at(m).data.at(v); + for (int c = 0; c < vhh.at(m)->components(reflevel); ++c) { + for (comm_state state(vartype); ! state.done(); state.step()) { + gv->ref_bnd_prolongate (state, tl, reflevel, c, mglevel, time); } } } @@ -89,31 +102,45 @@ namespace Carpet { } } - void SyncGVGroup ( const cGH* cgh, int group ) + // synchronises a set of group which all have the same vartype + void SyncGroups (const cGH* cgh, group_set& groups) { DECLARE_CCTK_PARAMETERS; const int tl = 0; - // make the comm_state loop the innermost - // in order to minimise the number of outstanding communications - if (minimise_outstanding_communications) { - for (int m=0; m<(int)arrdata.at(group).size(); ++m) { - for (int var=0; var<(int)arrdata.at(group).at(m).data.size(); ++var) { - for (int c=0; c<vhh.at(m)->components(reflevel); ++c) { - for (comm_state state; ! state.done(); state.step()) { - arrdata.at(group).at(m).data.at(var)->sync - (state, tl, reflevel, c, mglevel); + assert (groups.members.size() > 0); + + // Use collective or single-component buffers for communication ? + const int vartype = + use_collective_communication_buffers ? groups.vartype : -1; + + if (use_collective_communication_buffers || + ! minimise_outstanding_communications) { + for (comm_state state(vartype); ! state.done(); state.step()) { + for (int group = 0; group < groups.members.size(); ++group) { + const int g = groups.members.at(group); + for (int m = 0; m < arrdata.at(g).size(); ++m) { + for (int v = 0; v < arrdata.at(g).at(m).data.size(); ++v) { + ggf *const gv = arrdata.at(g).at(m).data.at(v); + for (int c = 0; c < vhh.at(m)->components(reflevel); ++c) { + gv->sync (state, tl, reflevel, c, mglevel); + } } } } } } else { - for (comm_state state; ! state.done(); state.step()) { - for (int m=0; m<(int)arrdata.at(group).size(); ++m) { - for (int var=0; var<(int)arrdata.at(group).at(m).data.size(); ++var) { - for (int c=0; c<vhh.at(m)->components(reflevel); ++c) { - arrdata.at(group).at(m).data.at(var)->sync - (state, tl, reflevel, c, mglevel); + // make the comm_state loop the innermost + // in order to minimise the number of outstanding communications + for (int group = 0; group < groups.members.size(); ++group) { + const int g = groups.members.at(group); + for (int m = 0; m < arrdata.at(g).size(); ++m) { + for (int v = 0; v < arrdata.at(g).at(m).data.size(); ++v) { + ggf *const gv = arrdata.at(g).at(m).data.at(v); + for (int c = 0; c < vhh.at(m)->components(reflevel); ++c) { + for (comm_state state(vartype); ! state.done(); state.step()) { + gv->sync (state, tl, reflevel, c, mglevel); + } } } } @@ -121,6 +148,7 @@ namespace Carpet { } } + int CheckSyncGroupConsistency ( const cGH* cgh,const char *groupname ) { int retval = 0; @@ -169,7 +197,6 @@ namespace Carpet { return retval; } - int EnableGroupComm (const cGH* cgh, const char* groupname) { // Communication is always enabled |