OpenAtom  Version1.5a
pcSectionManager.C
1 #include "pcSectionManager.h"
2 #include "paircalc/pcConfig.h"
3 
4 #include <algorithm>
5 
6 #ifdef USE_COMLIB
7 extern ComlibInstanceHandle mcastInstanceCP;
8 extern ComlibInstanceHandle mcastInstanceACP;
9 #endif
10 /** @addtogroup Ortho
11  @{
12 */
13 
14 namespace cp {
15  namespace ortho {
16 
17 void PCSectionManager::pup(PUP::er &p)
18 {
19  p | numPlanes;
20  p | numStates;
21  p | numChunks;
22  p | pcGrainSize;
23  p | orthoGrainSize;
24 
25  p | pcArrayID;
26  p | isSymmetric;
27  p | pcSection;
28 
29  p | orthoIndex;
30  p | orthomCastGrpID;
31  p | orthoRedGrpID;
32  p | msgPriority;
33 }
34 
35 
36 
37 /**
38  * The section manager now finds most of its init data from the global config class. If we need support for differently
39  * configured PC instances, we should make the section managers init themselves from an instance config object and not
40  * a global config object. But first, we need to implement the concept of a config class for an instance :)
41  */
42 void PCSectionManager::init(const CkIndex2D orthoIdx, const pc::pcConfig &pcCfg, CkArrayID pcAID, CkGroupID oMCastGID, CkGroupID oRedGID)
43 {
44  pcArrayID = pcAID;
45  isSymmetric = pcCfg.isSymmetric;
46 
47  numPlanes = pcCfg.numPlanes;
48  numStates = pcCfg.numStates;
49  numChunks = pcCfg.numChunks;
50  pcGrainSize = pcCfg.grainSize;
52 
53  orthoIndex = orthoIdx;
54  orthomCastGrpID = oMCastGID;
55  orthoRedGrpID = oRedGID;
57 }
58 
59 
60 
61 
62 /**
63  * Ortho chares are a 2D (nstates x nstates) array. ortho[sx,sy] talks to all the paircalc chares which handle
64  * the ordered pair of states (sx,sy). This will be pc[p,s1,s2,c] where p ranges across all planes and c across
65  * all chunks.
66  */
67 void PCSectionManager::createPCsection(const int s1, const int s2)
68 {
69  int ecount=0;
70  CkArrayIndex4D *elems=new CkArrayIndex4D[numPlanes*numChunks*2];
71  for(int chunk = numChunks-1; chunk >=0; chunk--)
72  for(int numX = numPlanes-1; numX >=0; numX--)
73  {
74  CkArrayIndex4D idx4d(numX,s1,s2,chunk);
75  elems[ecount++]=idx4d;
76  }
77  int numOrthoCol= pcGrainSize / orthoGrainSize;
78  int maxorthostateindex=(numStates / orthoGrainSize - 1) * orthoGrainSize;
79  int orthoIndexX=(orthoIndex.x * orthoGrainSize);
80 
81  orthoIndexX= (orthoIndexX>maxorthostateindex) ? maxorthostateindex : orthoIndexX;
82  int orthoIndexY=(orthoIndex.y * orthoGrainSize);
83  orthoIndexY= (orthoIndexY>maxorthostateindex) ? maxorthostateindex : orthoIndexY;
84  orthoIndexX-=s1;
85  orthoIndexY-=s2;
86  int orthoArrIndex=orthoIndexX*numOrthoCol+orthoIndexY;
87 
88  std::random_shuffle(elems, elems + ecount);
89 
90  /// Create and save this paircalc section
91  pcSection = CProxySection_PairCalculator::ckNew(pcArrayID, elems, ecount);
92  delete [] elems;
93 }
94 
95 
96 
97 
98 /**
99  * Initialize the planewise section reduction for Ortho sums across all planes and chunks
100  * pass through the the owning Ortho chare so the cookie can be placed in the 2d array
101  * (grainSize/orthoGrainSize)^2
102  *
103  * Ortho chares talk to paircalc chares based on their state indices. That is, results for an ordered pair of states
104  * (s1,s2) from an ortho will end up at the paircalc(s) responsible for that state pair. As paircalcs are decomposed
105  * along two other dimensions (planes & points), this results in a section of paircalcs which need to get data for
106  * any given state pair (s1,s2) via a multicast from the ortho responsible for that state pair (s1,s2).
107  *
108  * The same logic holds for input data from the paircalcs to ortho. As orthos are 2D and oblivious of any plane-wise
109  * or point-wise decomposition, all data pertaining to a state pair (s1,s2) from all the paircalcs mut be collated and
110  * delivered to the ortho that handles (s1,s2). This results in a reduction across a paircalc section that spans all
111  * planes and chunks of the paircalc array.
112  *
113  * An extra twist in these straightforward section rules happens because of the presence of phantom chares in symmetric
114  * paircalc instance. Phantom chares do not participate in the forward path and hence do not send any input data. Hence
115  * they should not be included in the reductions to ortho. However, they work in the backward path off the results from
116  * ortho and are hence included in the multicasts back to the paircalcs.
117  *
118  * We compound this a bit further in our greed to avoid extra work when possible. It should be noted that because of the
119  * limitations of the underlying matrix multiply libraries, we canNOT perform a triangular multiply on what is essentially
120  * symmetric input. Hence orthos orchestrate a square matrix multiply and end up with almost identical results (differing
121  * only by a transpose) in mirror chares across the array diagonal. Without going into the underlying math, we can say
122  * that the orthos that talk to phantom or on-diagonal pc chares end up with the exact data required, whereas the ortho
123  * chares that need to talk to the non-phantom sections, have to perform an additional transpose before they can pack the
124  * data off to their pc sections. This is where we get lazy and try to avoid this extra transpose if we can. Basically,
125  * when phantoms are turned off we rig the section creation so that the orthos which should have spoken to the phantoms
126  * instead talk to their non-phantom mirror sections. As these orthos have the data in the correct form already, no one
127  * has to perform any extra transposes.
128  *
129  * Hence orthos whose indices correspond to those of phantom paircalc chares, will talk to:
130  * - their original phantom section if the user turns on phantoms
131  * - a mirror non-phantom section if the user turns off phantoms
132  *
133  */
134 void PCSectionManager::setupArraySection(CkCallback cb, bool arePhantomsOn, bool useComlibForOrthoToPC)
135 {
136  int s1, s2;
137  /// Find the states indices of the paircalcs this ortho *should* be talking to.
138  CkIndex2D pc = computePCStateIndices(orthoIndex.x,orthoIndex.y);
139  /// When phantoms are off, ortho chares that should talk to a phantom section will instead talk to a mirror section
140  if (!arePhantomsOn && isSymmetric && pc.y<pc.x)
141  { s1 = pc.y; s2 = pc.x; }
142  else
143  { s1 = pc.x; s2 = pc.y; }
144 
145  #ifdef VERBOSE_SECTIONMANAGER
146  CkPrintf("Ortho[%d,%d] PCSectionManager setting up a paircalc section that includes PC[%d-%d,%d,%d,%d-%d,%d]\n",orthoIndex.x, orthoIndex.y,0,numPlanes-1,s1,s2,0,numChunks-1,isSymmetric);
147  #endif
148 
149  /// Create the paircalc section that this ortho chare will actually talk to
150  createPCsection(s1,s2);
151 
152  /// Paircalcs end their forward path by sending data to the orthos. Irrespective of their type (symm/asymm) or
153  /// whether phantoms are turned on or not, they always talk to the orthos corresponding to their state indices.
154  /// All the mirrors and section switching tricks that happen above only apply to the multicast back from ortho to
155  /// paircalc. Also, phantom paircalcs do not participate in the forward path and do not have any data to send.
156  /// Hence, only orthos whose indices correspond to the non-phantoms will register with their pc sections to get data
157  if ( !(isSymmetric && pc.y<pc.x) )
158  {
159  /// Delegate the pc section --> ortho reduction to CkMulticast
160  CkMulticastMgr *mcastGrp = CProxy_CkMulticastMgr(orthoRedGrpID).ckLocalBranch();
161  pcSection.ckSectionDelegate(mcastGrp);
162  /// Register this ortho chare with all the paircalcs in this section
163  initGRedMsg *gredMsg=new initGRedMsg;
164  gredMsg->cb=cb;
165  gredMsg->mCastGrpId= orthoRedGrpID;
166  gredMsg->lbsync=false;
167  gredMsg->orthoX=orthoIndex.x;
168  gredMsg->orthoY=orthoIndex.y;
169  pcSection.initGRed(gredMsg);
170  }
171 
172  /// Delegate the ortho --> pc section multicast to the appropriate library
173  if(useComlibForOrthoToPC)
174  {
175  #ifdef USE_COMLIB
176  CkPrintf("NOTE: Rectangular Send In USE\n");
177  if(isSymmetric)
178  ComlibAssociateProxy(mcastInstanceCP,pcSection);
179  else
180  ComlibAssociateProxy(mcastInstanceACP,pcSection);
181  #endif
182  }
183  else
184  {
185  CkMulticastMgr *mcastGrp = CProxy_CkMulticastMgr(orthomCastGrpID).ckLocalBranch();
186  pcSection.ckSectionDelegate(mcastGrp);
187  }
188 }
189 
190 
191 
192 
193 void PCSectionManager::sendResults(int n, internalType *ptr1, internalType *ptr2, int orthoX, int orthoY, int actionType, int priority)
194 {
195  #ifdef VERBOSE_SECTIONMANAGER
196  CkPrintf("PCSectionManager::sendResults()\n");
197  #endif
198 
199  /// Allocate a msg of the right size
200  multiplyResultMsg *omsg;
201  int size2 = (ptr2)? n : 0;
202  if(priority>0)
203  {
204  omsg=new (n, size2, 8*sizeof(int) ) multiplyResultMsg;
205  *(int*)CkPriorityPtr(omsg) = priority;
206  CkSetQueueing(omsg, CK_QUEUEING_IFIFO);
207  }
208  else
209  omsg=new (n, size2) multiplyResultMsg;
210 
211  /// Fill it with results
212  if(ptr2==NULL)
213  omsg->init1(n, ptr1, orthoX, orthoY, actionType);
214  else
215  omsg->init(n, n, ptr1, ptr2, orthoX, orthoY, actionType);
216  #ifdef _NAN_CHECK_
217  for(int i=0;i<n ;i++)
218  {
219  CkAssert( isfinite(ptr1[i]) );
220  CkAssert( isfinite(omsg->matrix1[i]) );
221  }
222  #endif
223 
224  /// Trigger the backward path for my paircalc section
225  pcSection.multiplyResult(omsg);
226 }
227 
228 
229 void PCSectionManager::sendMatrix(int n, internalType *ptr1, internalType *ptr2, int orthoX, int orthoY, int actionType, int priority)
230 {
231  #ifdef VERBOSE_SECTIONMANAGER
232  CkPrintf("PCSectionManager::sendMatrix()\n");
233  #endif
234 
235  /// Allocate a msg of the right size
236  multiplyResultMsg *omsg;
237  int size2 = (ptr2)? n : 0;
238  if(priority>0)
239  {
240  omsg=new (n, size2, 8*sizeof(int) ) multiplyResultMsg;
241  *(int*)CkPriorityPtr(omsg) = priority;
242  CkSetQueueing(omsg, CK_QUEUEING_IFIFO);
243  }
244  else
245  omsg=new (n, size2) multiplyResultMsg;
246 
247  /// Fill it with results
248  if(ptr2==NULL)
249  omsg->init1(n, ptr1, orthoX, orthoY, actionType);
250  else
251  omsg->init(n, n, ptr1, ptr2, orthoX, orthoY, actionType);
252  #ifdef _NAN_CHECK_
253  for(int i=0;i<n ;i++)
254  {
255  CkAssert( isfinite(ptr1[i]) );
256  CkAssert( isfinite(omsg->matrix1[i]) );
257  }
258  #endif
259 
260  /// Trigger the backward path for my paircalc section
261  pcSection.acceptOrthoT(omsg);
262 }
263 
264  } // end namespace ortho
265 } // end namespace cp
266 /*@}*/
bool isSymmetric
Is this a symmetric or asymmetric paircalc instance.
Definition: pcConfig.h:30
int inputMsgPriority
The priority (set by GSpace) of the input messages.
Definition: pcConfig.h:87
int numPlanes
The total number of planes in the system.
Definition: pcConfig.h:39
CkIndex2D computePCStateIndices()
Overloaded version that uses the stored ortho indices to compute the PC state indices.
CkArrayID pcArrayID
The array ID of the paircalc instance that I will manage comm with.
void pup(PUP::er &p)
PUP serializer.
int numStates
Number of states in this simulation.
int numStates
The total number of states in the system.
Definition: pcConfig.h:41
void sendMatrix(int n, internalType *ptr1, internalType *ptr2, int orthoX, int orthoY, int actionType, int priority)
Used to send OrthoT to the asymm instance. Replaces sendMatrix()
CProxySection_PairCalculator pcSection
The section of the array that my owner ortho chare will be talking to.
void createPCsection(const int s1, const int s2)
Create a paircalc section containing all chares with the specified two state indices.
int grainSize
The grain size along the states dimensions (plural) (number of states per PC chare) ...
Definition: pcConfig.h:45
CkGroupID orthomCastGrpID
The multicast and reduction groups that handle comm.
int numChunks
The number of chunks (4th dimension decomposition) of paircalcs.
int numChunks
The number of chunks (4th dimension of decomposition)
Definition: pcConfig.h:43
void sendResults(int n, internalType *ptr1, internalType *ptr2, int orthoX, int orthoY, int actionType, int priority)
Sends out the results to the paircalc section. Replaces finishPairCalcSection()
int pcGrainSize
The statewise decomposition grain size for the paircalcs.
int orthoGrainSize
The statewise decomposition grain size for the ortho chares.
Dumb structure that holds all the configuration inputs required for paircalc instantiation, functioning and interaction.
Definition: pcConfig.h:23
int orthoGrainSize
The grain size along the states dimensions for Ortho chares.
Definition: pcConfig.h:52
bool isSymmetric
Is this paircalc array a symmetric or asymmetric instance.
int numPlanes
Number of planes that GSpace is decomposed into.
void init(const CkIndex2D orthoIdx, const pc::pcConfig &pcCfg, CkArrayID pcAID, CkGroupID oMCastGID, CkGroupID oRedGID)
An initializer method that fills this with data.
CkIndex2D orthoIndex
The index of the calling Ortho chare.
int msgPriority
The priority to use for messages to PC.
void setupArraySection(CkCallback cb, bool arePhantomsOn, bool useComlibForOrthoToPC)
Creates a paircalc array section given the necessary info. Replaces initOneRedSect() ...