NAMD
ProxyMgr.C
Go to the documentation of this file.
1 
7 #include "InfoStream.h"
8 #include "main.h"
9 #include "BOCgroup.h"
10 #include "ProxyMgr.decl.h"
11 #include "ProxyMgr.h"
12 #include "PatchMap.inl"
13 #include "ProxyPatch.h"
14 #include "ComputeMap.h"
15 #include "HomePatch.h"
16 #include <string.h>
17 #include "ProcessorPrivate.h"
18 #include "packmsg.h"
19 #include "Priorities.h"
20 #ifndef _NO_ALLOCA_H
21 #include <alloca.h>
22 #endif
23 #ifndef _NO_MALLOC_H
24 #include <malloc.h>
25 #endif
26 
27 #include <map>
28 #include <vector>
29 #include <algorithm>
30 
31 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR) && (CMK_SMP) && defined(NAMDSRC_IMMQD_HACK)
32 #include "qd.h"
33 #endif
34 
35 #include "SimParameters.h"
36 #include "Node.h"
37 
38 //#define DEBUGM
39 #define MIN_DEBUG_LEVEL 2
40 #include "Debug.h"
41 
42 #define ALLOCA(TYPE,NAME,SIZE) TYPE *NAME = (TYPE *) alloca((SIZE)*sizeof(TYPE))
43 
46 //"proxySpanDim" is a configuration parameter as "proxyTreeBranchFactor" in configuration file
47 int proxySpanDim = 4;
49 
51  PACK(patch);
52  PACK(node);
53  PACK_RESIZE(tree);
54 )
55 
57 
58  int msg_size = 0;
59  msg_size += sizeof(msg->node);
60  msg_size += sizeof(msg->patch);
61 
62  int j;
63  for ( j = 0; j < Results::maxNumForces; ++j ) {
64  int array_size = msg->forceList[j]->size();
65  msg_size += sizeof(array_size);
66  msg_size += array_size * sizeof(char);
67  msg_size = ALIGN_8 (msg_size);
68  Force* f = msg->forceList[j]->begin();
69  int nonzero_count = 0;
70  for ( int i = 0; i < array_size; ++i ) {
71  if ( f[i].x != 0. || f[i].y != 0. || f[i].z != 0. ) { ++nonzero_count; }
72  }
73  msg_size += nonzero_count * sizeof(Vector);
74  }
75 
76  void *msg_buf = CkAllocBuffer(msg,msg_size);
77  char *msg_cur = (char *)msg_buf;
78 
79  CmiMemcpy((void*)msg_cur,(void*)(&(msg->node)),sizeof(msg->node));
80  msg_cur += sizeof(msg->node);
81  CmiMemcpy((void*)msg_cur,(void*)(&(msg->patch)),sizeof(msg->patch));
82  msg_cur += sizeof(msg->patch);
83  for ( j = 0; j < Results::maxNumForces; ++j ) {
84  int array_size = msg->forceList[j]->size();
85  *(int *) msg_cur = array_size;
86  msg_cur += sizeof(int);
87  char *nonzero = msg_cur;
88  msg_cur += array_size * sizeof(char);
89  msg_cur = (char *)ALIGN_8 (msg_cur);
90  Vector *farr = (Vector *)msg_cur;
91  Force* f = msg->forceList[j]->begin();
92 
93  for ( int i = 0; i < array_size; ++i ) {
94  if ( f[i].x != 0. || f[i].y != 0. || f[i].z != 0. ) {
95  nonzero[i] = 1;
96  farr->x = f[i].x;
97  farr->y = f[i].y;
98  farr->z = f[i].z;
99  farr ++;
100  } else {
101  nonzero[i] = 0;
102  }
103  }
104  msg_cur = (char *) farr;
105  }
106 
107  delete msg;
108  return msg_buf;
109 }
110 
112 
113  void *vmsg = CkAllocBuffer(ptr,sizeof(ProxyResultMsg));
114  ProxyResultMsg *msg = new (vmsg) ProxyResultMsg;
115  char *msg_cur = (char*)ptr;
116 
117  CmiMemcpy((void*)(&(msg->node)),(void*)msg_cur,sizeof(msg->node));
118  msg_cur += sizeof(msg->node);
119  CmiMemcpy((void*)(&(msg->patch)),(void*)msg_cur,sizeof(msg->patch));
120  msg_cur += sizeof(msg->patch);
121  int j;
122  for ( j = 0; j < Results::maxNumForces; ++j ) {
123  int array_size = *(int *) msg_cur;
124  msg_cur += sizeof(array_size);
125  msg->forceList[j] = &(msg->forceListInternal[j]);
126  msg->forceList[j]->resize(array_size);
127  char *nonzero = msg_cur;
128  msg_cur += array_size * sizeof(char);
129  msg_cur = (char *)ALIGN_8 (msg_cur);
130  Vector* farr = (Vector *) msg_cur;
131  Force* f = msg->forceList[j]->begin();
132  for ( int i = 0; i < array_size; ++i ) {
133  if ( nonzero[i] ) {
134  f[i].x = farr->x;
135  f[i].y = farr->y;
136  f[i].z = farr->z;
137  farr++;
138  } else {
139  f[i].x = 0.; f[i].y = 0.; f[i].z = 0.;
140  }
141  }
142  msg_cur = (char *) farr;
143  }
144 
145  CkFreeMsg(ptr);
146  return msg;
147 }
148 
150 
151  //1. decide the length of forceArr and iszero field.
152  int tmpLen[Results::maxNumForces];
153  int iszeroLen = 0;
154  for (int i=0; i<Results::maxNumForces; i++){
155  tmpLen[i] = fls[i].size();
156  iszeroLen += tmpLen[i];
157  }
158  char *tmpIszero = new char[iszeroLen];
159  char *iszeroPtr = tmpIszero;
160  int fArrLen = 0;
161  for(int i=0; i<Results::maxNumForces; i++) {
162  Force *fiPtr = fls[i].begin();
163  for(int j=0; j<tmpLen[i]; j++, fiPtr++, iszeroPtr++) {
164  if(fiPtr->x!=0.0 || fiPtr->y!=0.0 || fiPtr->z!=0) {
165  *iszeroPtr=0;
166  fArrLen++;
167  }else{
168  *iszeroPtr=1;
169  }
170  }
171  }
172 
173  //2. Ready to create the msg, and set all fields
174  ProxyResultVarsizeMsg *retmsg = new(fArrLen, iszeroLen, prioSize)ProxyResultVarsizeMsg;
175  retmsg->node = nid;
176  retmsg->patch = pid;
177  memcpy(retmsg->flLen, tmpLen, sizeof(int)*Results::maxNumForces);
178  iszeroPtr = tmpIszero;
179  Force *forcePtr = retmsg->forceArr;
180  for(int i=0; i<Results::maxNumForces; i++) {
181  Force *fiPtr = fls[i].begin();
182  for(int j=0; j<tmpLen[i]; j++, fiPtr++, iszeroPtr++) {
183  if((*iszeroPtr)!=1) {
184  forcePtr->x = fiPtr->x;
185  forcePtr->y = fiPtr->y;
186  forcePtr->z = fiPtr->z;
187  forcePtr++;
188  }
189  }
190  }
191  memcpy(retmsg->isZero, tmpIszero, sizeof(char)*iszeroLen);
192  delete [] tmpIszero;
193  return retmsg;
194 }
195 
197  int numAllPes = 0;
198  for(int i=0; i<size; i++) {
199  numAllPes += tree[i].numPes;
200  }
201  ProxyNodeAwareSpanningTreeMsg *retmsg = new(size, numAllPes, 0) ProxyNodeAwareSpanningTreeMsg;
202  retmsg->patch = pid;
203  retmsg->procID = nid;
204  retmsg->numNodesWithProxies = size;
205  int *pAllPes = retmsg->allPes;
206  for(int i=0; i<size; i++) {
207  retmsg->numPesOfNode[i] = tree[i].numPes;
208  for(int j=0; j<tree[i].numPes; j++) {
209  *pAllPes = tree[i].peIDs[j];
210  pAllPes++;
211  }
212  }
213  return retmsg;
214 }
215 
216 //Only available when macro PROCTRACE_DEBUG is defined
218 #ifdef PROCTRACE_DEBUG
219  DebugFileTrace *dft = DebugFileTrace::Object();
220  dft->openTrace();
221  const char *patchname = "ProxyPatch";
222  if(procID == CkMyPe()) patchname = "HomePatch";
223  dft->writeTrace("%s: %s[%d] on proc %d node %d has ST (src %d) with %d nodes\n",
224  tag, patchname, patch, CkMyPe(), CkMyNode(), procID, numNodesWithProxies);
225  if(numNodesWithProxies==0) {
226  dft->closeTrace();
227  return;
228  }
229  dft->writeTrace("%s: ===%d===pes/node: ", tag, patch);
230  for(int i=0; i<numNodesWithProxies; i++) {
231  dft->writeTrace("%d ", numPesOfNode[i]);
232  }
233  dft->writeTrace("\n%s: ===%d===pe list: ", tag, patch);
234  int *p = allPes;
235  for(int i=0; i<numNodesWithProxies; i++) {
236  for(int j=0; j<numPesOfNode[i]; j++) {
237  dft->writeTrace("%d ", *p);
238  p++;
239  }
240  }
241  dft->writeTrace("\n");
242  dft->closeTrace();
243 #endif
244 }
245 
246 // for spanning tree
248  int totalFLLen=0;
249  int nonzero_count = 0;
250  int nodeSize = msg->nodes.size();
251  for (int j = 0; j < Results::maxNumForces; ++j ) {
252  int array_size = msg->forceList[j]->size();
253  totalFLLen += array_size;
254  Force* f = msg->forceList[j]->begin();
255  for ( int i = 0; i < array_size; ++i ) {
256  if ( f[i].x != 0. || f[i].y != 0. || f[i].z != 0. ) { ++nonzero_count; }
257  }
258  }
259 
260  ProxyCombinedResultRawMsg *msg_buf = new(nodeSize, totalFLLen, nonzero_count, PRIORITY_SIZE)ProxyCombinedResultRawMsg;
261  //Copy envelope stuff
262  {
263  envelope *oenv = UsrToEnv(msg);
264  envelope *nenv = UsrToEnv(msg_buf);
265  CmiMemcpy(nenv->getPrioPtr(), oenv->getPrioPtr(), nenv->getPrioBytes());
266  }
267 
268  msg_buf->nodeSize = nodeSize;
269  for (int i=0; i<nodeSize; i++) {
270  msg_buf->nodes[i] = msg->nodes[i];
271  }
272  #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
273  msg_buf->destPe = msg->destPe;
274  #if CMK_SMP && defined(NAMDSRC_IMMQD_HACK)
275  msg_buf->isFromImmMsgCall = msg->isFromImmMsgCall;
276  #endif
277  #endif
278  msg_buf->patch = msg->patch;
279 
280  Force *farr = msg_buf->forceArr;
281  char *isNonZeroPtr = msg_buf->isForceNonZero;
282  for ( int j = 0; j < Results::maxNumForces; ++j ) {
283  int array_size = msg->forceList[j]->size();
284  msg_buf->flLen[j] = array_size;
285  Force* f = msg->forceList[j]->begin();
286  for ( int i = 0; i < array_size; ++i , isNonZeroPtr++) {
287  if ( f[i].x != 0. || f[i].y != 0. || f[i].z != 0. ) {
288  *isNonZeroPtr = 1;
289  farr->x = f[i].x;
290  farr->y = f[i].y;
291  farr->z = f[i].z;
292  farr ++;
293  } else {
294  *isNonZeroPtr = 0;
295  }
296  }
297  }
298  delete msg;
299  return msg_buf;
300 }
301 
303 
304  //CkPrintf("[%d]: unpacking: plainData=%p\n", CkMyPe(), ptr->plainData);
305 
306  void *vmsg = CkAllocBuffer(ptr,sizeof(ProxyCombinedResultMsg));
308 
309  for (int i=0; i<ptr->nodeSize; i++) {
310  msg->nodes.add(ptr->nodes[i]);
311  }
312  #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
313  msg->destPe = ptr->destPe;
314  #if CMK_SMP && defined(NAMDSRC_IMMQD_HACK)
315  msg->isFromImmMsgCall = ptr->isFromImmMsgCall;
316  #endif
317  #endif
318  msg->patch = ptr->patch;
319 
320  char *nonzero = ptr->isForceNonZero;
321  Force* farr = ptr->forceArr;
322 
323  for ( int j = 0; j < Results::maxNumForces; ++j ) {
324  int array_size = ptr->flLen[j];
325  msg->forceList[j] = &(msg->forceListInternal[j]);
326  msg->forceList[j]->resize(array_size);
327  Force* f = msg->forceList[j]->begin();
328 
329  for ( int i = 0; i < array_size; ++i, nonzero++ ) {
330  if ( *nonzero ) {
331  f[i].x = farr->x;
332  f[i].y = farr->y;
333  f[i].z = farr->z;
334  farr++;
335  } else {
336  f[i].x = 0.; f[i].y = 0.; f[i].z = 0.;
337  }
338  }
339  }
340 
341  delete ptr;
342  return msg;
343 }
344 
345 // class static
346 int ProxyMgr::nodecount = 0;
347 
349  if (CkpvAccess(ProxyMgr_instance)) {
350  NAMD_bug("Tried to create ProxyMgr twice.");
351  }
352  CkpvAccess(ProxyMgr_instance) = this;
353 }
354 
356  removeProxies();
357  CkpvAccess(ProxyMgr_instance) = NULL;
358 }
359 
360 
362  if(CkMyRank()!=0) return;
363  proxySendSpanning = 1;
364 }
365 
367  return proxySendSpanning;
368 }
369 
371  if(CkMyRank()!=0) return;
372  proxyRecvSpanning = 1;
373 }
374 
376  return proxyRecvSpanning;
377 }
378 
380  if(CkMyRank()!=0) return;
381  proxySpanDim = dim;
382 }
383 
385  return ptree;
386 }
387 
389 {
390  ProxySetIter pi(proxySet);
391  for ( pi = pi.begin(); pi != pi.end(); pi++)
392  {
393  delete pi->proxyPatch;
394  }
395  proxySet.clear();
396 }
397 
399 {
400  ResizeArray<PatchID> toDelete;
401  ProxySetIter pi(proxySet);
402  for ( pi = pi.begin(); pi != pi.end(); pi++)
403  {
404  if ( pi->proxyPatch->getNumComputes() == 0 ) {
405  toDelete.add(pi->patchID);
406  //fprintf(stderr, "Proxy Deleted Patch %d Proc %d", pi->patchID, CkMyPe());
407  }
408  }
409  PatchID *pidi = toDelete.begin();
410  for ( ; pidi != toDelete.end(); ++pidi ) {
411  removeProxy(*pidi);
412  }
413 }
414 
415 // Figure out which proxies we need and create them
417 {
418  // Delete the old proxies.
419  removeProxies();
420 
421  PatchMap *patchMap = PatchMap::Object();
422  int numPatches = patchMap->numPatches();
423  int myNode = CkMyPe();
424  enum PatchFlag { Unknown, Home, NeedProxy };
425  int *patchFlag = new int[numPatches];
426  int i, j;
427 
428  // Note all home patches.
429  for ( i = 0; i < numPatches; ++i )
430  {
431  patchFlag[i] = ( patchMap->node(i) == myNode ) ? Home : Unknown;
432  }
433 
434 #if !(defined(NAMD_CUDA) || defined(NAMD_HIP))
435  // Add all upstream neighbors.
436  PatchID neighbors[PatchMap::MaxOneAway];
437  PatchIDList basepids;
438  patchMap->basePatchIDList(myNode,basepids);
439  for ( i = 0; i < basepids.size(); ++i )
440  {
441  if ( patchMap->node(basepids[i]) != myNode ) {
442  patchFlag[basepids[i]] = NeedProxy;
443  }
444  int numNeighbors = patchMap->upstreamNeighbors(basepids[i],neighbors);
445  for ( j = 0; j < numNeighbors; ++j )
446  {
447  if ( ! patchFlag[neighbors[j]] ) {
448  patchFlag[neighbors[j]] = NeedProxy;
449  }
450  }
451  }
452 #endif
453 
454  ComputeMap *computeMap = ComputeMap::Object();
455 
456  // Check all patch-based compute objects.
457  int nc = computeMap->numComputes();
458  for ( i = 0; i < nc; ++i )
459  {
460 #if defined(NAMD_CUDA) || defined(NAMD_HIP)
461  ComputeType t = computeMap->type(i);
463  continue;
464 #elif defined(NAMD_MIC)
465  ComputeType t = computeMap->type(i);
466  if ( computeMap->directToDevice(i) != 0 ) { continue; } // NOTE: Compute for device will take care of requiring the patch
467 #endif
468  if ( computeMap->node(i) != myNode )
469  continue;
470  int numPid = computeMap->numPids(i);
471  for ( j = 0; j < numPid; ++j )
472  {
473  int pid = computeMap->pid(i,j);
474  if ( ! patchFlag[pid] ) {
475  patchFlag[pid] = NeedProxy;
476  }
477  }
478  }
479  // Create proxy list
480  for ( i = 0; i < numPatches; ++i ) {
481  if ( patchFlag[i] == NeedProxy )
482  { // create proxy patch
483  ProxyPatch *proxy = new ProxyPatch(i);
484  proxySet.add(ProxyElem(i, proxy));
485  patchMap->registerPatch(i, proxy);
486  }
487  }
488  delete[] patchFlag;
489 }
490 
491 void
493  Patch *p = PatchMap::Object()->patch(pid);
494  if (!p) {
495  DebugM(4,"createProxy("<<pid<<")\n");
496  ProxyPatch *proxy = new ProxyPatch(pid);
497  proxySet.add(ProxyElem(pid,proxy));
498  PatchMap::Object()->registerPatch(pid,proxy);
499  }
500  else {
501  DebugM(4,"createProxy("<<pid<<") found " << p->getPatchID() << "\n");
502  }
503 
504 }
505 
506 void
508  ProxyElem *p = proxySet.find(ProxyElem(pid));
509  if (p) {
511  delete p->proxyPatch;
512  proxySet.del(ProxyElem(pid));
513  // iout << iINFO << "Removing unused proxy " << pid << " on " << iPE << ".\n" << endi;
514  }
515 }
516 
517 void
519  // determine which node gets message
520  NodeID node = PatchMap::Object()->node(pid);
521 
523 
524  msg->node=CkMyPe();
525  msg->patch = pid;
526 
527  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
528  cp[node].recvRegisterProxy(msg);
529 }
530 
531 void
533  HomePatch *homePatch = PatchMap::Object()->homePatch(msg->patch);
534  homePatch->registerProxy(msg); // message deleted in registerProxy()
535 }
536 
537 void
539  // determine which node gets message
540  NodeID node = PatchMap::Object()->node(pid);
541 
543 
544  msg->node=CkMyPe();
545  msg->patch = pid;
546 
547  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
548  cp[node].recvUnregisterProxy(msg);
549 }
550 
551 void
553  HomePatch *homePatch = PatchMap::Object()->homePatch(msg->patch);
554  homePatch->unregisterProxy(msg); // message deleted in registerProxy()
555 }
556 
557 void
559 {
560  PatchIDList pids;
561  if (!CkMyPe()) iout << iINFO << "Building spanning tree ... send: " << proxySendSpanning << " recv: " << proxyRecvSpanning
562  << " with branch factor " << proxySpanDim <<"\n" << endi;
564  for (int i=0; i<pids.size(); i++) {
565  HomePatch *home = PatchMap::Object()->homePatch(pids[i]);
566  if (home == NULL) CkPrintf("ERROR: homepatch NULL\n");
567 #ifdef NODEAWARE_PROXY_SPANNINGTREE
568  home->buildNodeAwareSpanningTree();
569 #else
570  home->buildSpanningTree();
571 #endif
572  }
573 }
574 
575 void
577 {
578 #if 0
579  //The homePatchIDList is an expensive as it goes through
580  //every patch ids.
581  PatchIDList pids;
583  for (int i=0; i<pids.size(); i++) {
584  HomePatch *home = PatchMap::Object()->homePatch(pids[i]);
585  if (home == NULL) CkPrintf("ERROR: homepatch NULL\n");
586  home->sendProxies();
587  }
588 #else
590  HomePatchListIter iter(*hpl);
591  for(iter=iter.begin(); iter!=iter.end(); iter++) {
592  HomePatch *home = iter->patch;
593  home->sendProxies();
594  }
595 #endif
596 }
597 
598 void
599 ProxyMgr::sendProxies(int pid, int *list, int n)
600 {
601  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
602  cp[0].recvProxies(pid, list, n);
603 }
604 
605 //The value defines the max number of intermediate proxies (acting
606 //as the node to relay proxy msgs to children) allowed to reside
607 //on a physical node for proxy spanning tree
608 #define MAX_INTERNODE 1
609 
610 //Only for debug
611 static void outputProxyTree(ProxyTree &ptree, int np){
612  FILE *ofp = fopen("patch_proxylist.txt", "w");
613  std::vector<int> plist;
614  for(int i=0; i<np; i++) {
615  fprintf(ofp, "%d: ", i);
616  int listlen = ptree.proxylist[i].size();
617  fprintf(ofp, "#%d ", listlen);
618  plist.clear();
619  for(int j=0; j<listlen; j++) {
620  plist.push_back(ptree.proxylist[i][j]);
621  }
622  std::sort(plist.begin(), plist.end());
623  for(int j=0; j<listlen; j++) {
624  fprintf(ofp, "%d ", plist[j]);
625  }
626  fprintf(ofp, "\n");
627  }
628  fclose(ofp);
629 }
630 
631 // only on PE 0
632 void
633 ProxyMgr::recvProxies(int pid, int *list, int n)
634 {
635  int nPatches = PatchMap::Object()->numPatches();
636  if (ptree.proxylist == NULL)
637  ptree.proxylist = new NodeIDList[nPatches];
638  ptree.proxylist[pid].resize(n);
639  for (int i=0; i<n; i++)
640  ptree.proxylist[pid][i] = list[i];
641  ptree.proxyMsgCount ++;
642  if (ptree.proxyMsgCount == nPatches) {
643  //debug
644  //outputProxyTree(ptree, nPatches);
645 
646  ptree.proxyMsgCount = 0;
647  // building and sending of trees is done in two steps now
648  // so that the building step can be shifted to the load balancer
649 #ifdef NODEAWARE_PROXY_SPANNINGTREE
650  buildNodeAwareSpanningTree0();
651 #else
653 #endif
655  }
656 }
657 
659  int nPatches = PatchMap::Object()->numPatches();
660  if(ptree.proxylist == NULL) ptree.proxylist = new NodeIDList[nPatches];
661  CmiAssert(msg->numPatches == nPatches);
662  int peIdx = 0;
663  for(int i=0; i<nPatches; i++) {
664  int pid = msg->patchIDs[i];
665  int plen = msg->proxyListLen[i];
666  ptree.proxylist[pid].resize(plen);
667  for(int j=0; j<plen; j++) {
668  ptree.proxylist[pid][j] = msg->proxyPEs[peIdx++];
669  }
670  }
671  delete msg;
672 
673  //debug
674  //outputProxyTree(ptree, nPatches);
675 
676  ptree.proxyMsgCount = 0;
677  // building and sending of trees is done in two steps now
678  // so that the building step can be shifted to the load balancer
679 #ifdef NODEAWARE_PROXY_SPANNINGTREE
680  buildNodeAwareSpanningTree0();
681 #else
683 #endif
685 }
686 
687 //
688 // XXX static and global variables are unsafe for shared memory builds.
689 // The global and static vars should be eliminated.
690 // Unfortunately, the routines that use these below are actually
691 // in use in NAMD.
692 //
693 extern double *cpuloads;
694 static int *procidx = NULL;
695 static double averageLoad = 0.0;
696 
697 static int compLoad(const void *a, const void *b)
698 {
699  int i1 = *(int *)a;
700  int i2 = *(int *)b;
701  double d1 = cpuloads[i1];
702  double d2 = cpuloads[i2];
703  if (d1 < d2)
704  return 1;
705  else if (d1 == d2)
706  return 0;
707  else
708  return -1;
709  // sort from high to low
710 }
711 
712 static void processCpuLoad()
713 {
714  int i;
715  if (!procidx) {
716  procidx = new int[CkNumPes()];
717  }
718  for (i=0; i<CkNumPes(); i++) procidx[i] = i;
719  qsort(procidx, CkNumPes(), sizeof(int), compLoad);
720 
721  double averageLoad = 0.0;
722  for (i=0; i<CkNumPes(); i++) averageLoad += cpuloads[i];
723  averageLoad /= CkNumPes();
724 // iout << "buildSpanningTree1: no intermediate node on " << procidx[0] << " " << procidx[1] << endi;
725 
726 }
727 
728 static int noInterNode(int p)
729 {
730  int exclude = 0;
731  if(CkNumPes()<1025)
732  exclude = 5;
733  else if(CkNumPes()<4097)
734  exclude = 10;
735  else if(CkNumPes()<8193)
736  exclude = 40;
737  else if(CkNumPes()<16385)
738  exclude = 40;
739  else
740  exclude = 80;
741  for (int i=0; i<exclude; i++) if (procidx[i] == p) return 1;
742 // if (cpuloads[p] > averageLoad) return 1;
743  return 0;
744 }
745 
746 #ifdef NODEAWARE_PROXY_SPANNINGTREE
747 //only on PE 0
748 void ProxyMgr::buildNodeAwareSpanningTree0(){
749  CkPrintf("Info: build node-aware spanning tree with send: %d, recv: %d with branch factor %d\n",
751  int numPatches = PatchMap::Object()->numPatches();
752  if (ptree.naTrees == NULL) ptree.naTrees = new proxyTreeNodeList[numPatches];
753  for (int pid=0; pid<numPatches; pid++)
754  buildSinglePatchNodeAwareSpanningTree(pid, ptree.proxylist[pid], ptree.naTrees[pid]);
755 
756 
757  //Debug
758  //printf("#######################Naive ST#######################\n");
759  //printProxySpanningTree();
760 
761  //Now the naive spanning tree has been constructed and stored in oneNATree;
762  //Afterwards, some optimizations on this naive spanning tree could be done.
763  //except the first element as the tree root always contains the processor
764  //that has home patch
765 
766  //1st Optimization: reduce intermediate nodes as much as possible. In details,
767  //the optimal case is that on a single physical smp node, there should be no
768  //two proxies who act as the intermediate nodes to pass information to childrens
769  //in the spanning tree. E.g, for patch A's proxy spanning tree, it has a node X as
770  //its intermediate node. However, for patch B's, it also has a node X as its intermediate
771  //node. We should avoid this situation as node X becomes the bottleneck as it has twice
772  //amount of work to process now.
773  //Step1: foward to the first patch that has proxies
774  //Now proxyNodeMap records the info that how many intermediate nodes on a node
775  //each element indiates the number of proxies residing on this node
776  int pid=0;
777  for(;pid<numPatches; pid++) {
778  if(ptree.proxylist[pid].size()>0) break;
779  }
780  if(pid==numPatches) {
781  return;
782  }
783  int *proxyNodeMap = new int[CkNumNodes()];
784  memset(proxyNodeMap, 0, sizeof(int)*CkNumNodes());
785  {
786  proxyTreeNodeList &onePatchT = ptree.naTrees[pid];
787  //If a node is an intermediate node, then its idx should satisfy
788  //idx*proxySpanDim + 1 < onePatchT.size()
789  int lastInterNodeIdx = (onePatchT.size()-2)/proxySpanDim;
790  for(int i=1; i<lastInterNodeIdx; i++) { //excluding the root node
791  int nid = onePatchT.item(i).nodeID;
792  proxyNodeMap[nid]++;
793  }
794  }
795  //Step2: iterate over each patch's proxy spanning tree to adjust
796  //the tree node positions. The bad thing here is that it may involve
797  //many memory allocations and deallocation for small-size (~100bytes)
798  //chunks.
799  pid++; //advance to the next patch
800  for(; pid<numPatches; pid++) {
801  if(ptree.proxylist[pid].size()==0) continue;
802  proxyTreeNodeList &onePatchT = ptree.naTrees[pid];
803  int lastInterNodeIdx = (onePatchT.size()-2)/proxySpanDim;
804  for(int i=1; i<=lastInterNodeIdx; i++) {
805  int nid = onePatchT.item(i).nodeID;
806  if(proxyNodeMap[nid]<MAX_INTERNODE) {
807  proxyNodeMap[nid]++;
808  continue;
809  }
810  //the position is occupied, so search the children
811  //nodes to see whether there's one to swap this node
812  //if not found, find the first position that has smallest
813  //amount of nodes.
814  int leastIdx = -1;
815  int leastAmount = ~(1<<31);
816  //iterate children nodes
817  int swapPos;
818  for(swapPos=lastInterNodeIdx+1; swapPos<onePatchT.size(); swapPos++) {
819  int chiNId = onePatchT.item(swapPos).nodeID;
820  if(proxyNodeMap[chiNId]<MAX_INTERNODE) {
821  break;
822  }
823  if(proxyNodeMap[chiNId]<leastAmount) {
824  leastAmount = proxyNodeMap[chiNId];
825  leastIdx = swapPos;
826  }
827  }
828  if(swapPos==onePatchT.size()) {
829  CmiAssert(leastIdx!=-1); //because the above loop at least executes once
830  //indicate we cannot find a physical node which
831  //still allows the intermediate proxy.
832  swapPos = leastIdx;
833  }
834  //swap the current proxy tree node "i" with node "swapPos"
835  proxyTreeNode *curNode = &onePatchT.item(i);
836  proxyTreeNode *swapNode = &onePatchT.item(swapPos);
837  proxyNodeMap[swapNode->nodeID]++; //update the proxyNodeMap record
838  int tmp = curNode->nodeID;
839  curNode->nodeID = swapNode->nodeID;
840  swapNode->nodeID = tmp;
841  tmp = curNode->numPes;
842  curNode->numPes = swapNode->numPes;
843  swapNode->numPes = tmp;
844  int *tmpPes = curNode->peIDs;
845  curNode->peIDs = swapNode->peIDs;
846  swapNode->peIDs = tmpPes;
847  }
848  }
849  delete [] proxyNodeMap;
850 
851  //Debug
852  //printf("#######################After 1st optimization#######################\n");
853  //printProxySpanningTree();
854 
855  //2nd optimization: similar to the 1st optimization but now thinking in
856  //the core level. If we cannot avoid place two intermediate proxy
857  //on the same node, we'd better to place them in different cores inside
858  //the node
859  if(CmiMyNodeSize()==1) {
860  //No need to perform the second optimization as every node has only 1 core
861  return;
862  }
863  //Step1: forward to the first patch that has proxies
864  pid=0;
865  for(;pid<numPatches; pid++) {
866  if(ptree.proxylist[pid].size()>0) break;
867  }
868  if(pid==numPatches) {
869  return;
870  }
871  int *proxyCoreMap = new int[CkNumPes()];
872  memset(proxyCoreMap, 0, sizeof(int)*CkNumPes());
873  {
874  proxyTreeNodeList &onePatchT = ptree.naTrees[pid];
875  //If a node is an intermediate node, then its idx should satisfy
876  //idx*proxySpanDim + 1 < onePatchT.size()
877  int lastInterNodeIdx = (onePatchT.size()-2)/proxySpanDim;
878  for(int i=1; i<lastInterNodeIdx; i++) { //excluding the root node
879  int rootProcID = onePatchT.item(i).peIDs[0];
880  proxyCoreMap[rootProcID]++;
881  }
882  }
883  //Step2: iterate over each patch's proxy spanning tree to adjust
884  //the root's position of intermediate proxies.
885  pid++; //advance to the next patch
886  for(; pid<numPatches; pid++) {
887  if(ptree.proxylist[pid].size()==0) continue;
888  proxyTreeNodeList &onePatchT = ptree.naTrees[pid];
889  int lastInterNodeIdx = (onePatchT.size()-2)/proxySpanDim;
890  for(int i=1; i<=lastInterNodeIdx; i++) {
891  proxyTreeNode *curNode = &onePatchT.item(i);
892  int rootProcID = curNode->peIDs[0];
893  if(curNode->numPes==1 || proxyCoreMap[rootProcID]<MAX_INTERNODE){
894  //if this node contains only 1 core, then we have to leave it as it is
895  //because there are no other cores in the same node that could be used to
896  //adjust
897  proxyCoreMap[rootProcID]++;
898  continue;
899  }
900 
901  //foound more than MAX_INTERNODE intermediate proxies on the same core,
902  //adjust the root id of the core of this proxy tree node
903  int leastIdx = -1;
904  int leastAmount = ~(1<<31);
905  //iterate children nodes
906  int swapPos;
907 
908  for(swapPos=1; swapPos<curNode->numPes; swapPos++) {
909  int otherCoreID = curNode->peIDs[swapPos];
910  if(proxyCoreMap[otherCoreID]<MAX_INTERNODE) {
911  break;
912  }
913  if(proxyCoreMap[otherCoreID]<leastAmount) {
914  leastAmount = proxyCoreMap[otherCoreID];
915  leastIdx = swapPos;
916  }
917  }
918  if(swapPos==curNode->numPes) {
919  CmiAssert(leastIdx!=-1); //because the above loop body must execute at least once
920  //indicate we cannot find a physical node which
921  //still allows the intermediate proxy.
922  swapPos = leastIdx;
923  }
924  int tmp = curNode->peIDs[swapPos];
925  curNode->peIDs[swapPos] = curNode->peIDs[0];
926  curNode->peIDs[0] = tmp;
927  proxyCoreMap[tmp]++;
928  }
929  }
930 
931  delete proxyCoreMap;
932 
933  //Debug
934  //printf("#######################After 2nd optimization#######################\n");
935  //printProxySpanningTree();
936 }
937 
938 void ProxyMgr::buildSinglePatchNodeAwareSpanningTree(PatchID pid, NodeIDList &proxyList,
939  proxyTreeNodeList &ptnTree){
940  int numProxies = proxyList.size();
941  if (numProxies == 0) {
942  //CkPrintf ("This is sheer evil in building node-aware spanning tree!\n\n");
943  return;
944  }
945 
946  //usually the #proxies is at most 62 (considering 2-away in all dimensions)
947  //so the access in proxyNodeMap and proxyTreeIdx is at most log2(62)=8 if
948  //all proxies are in different nodes
949  //could be better than a CkNumNodes() array in that cache perf. is better
950  //because of the reduced memory footprint -Chao Mei
951  std::map<int, int> proxyNodeMap; //<node id, numProxies>
952  std::vector<int> proxyNodeIDs;
953  std::map<int, int> proxyTreeIdx; //<node id, idx in proxyNodeIDs>
954 
955  //the processor id of home patch
956  int hpProcID = PatchMap::Object()->node(pid);
957  int hpNodeID = CkNodeOf(hpProcID);
958  proxyNodeMap[hpNodeID]=1;
959  proxyTreeIdx[hpNodeID]=0;
960  proxyNodeIDs.push_back(hpNodeID);
961  //proxyNodeList[0] = hpNodeID;
962  //int numNodesWithProxies = 1;
963 
964  for(int i=0; i<numProxies; i++) {
965  int procId = proxyList[i];
966  int nodeId = CkNodeOf(procId);
967  std::map<int, int>::iterator it=proxyNodeMap.find(nodeId);
968  if(it==proxyNodeMap.end()) {
969  proxyNodeMap[nodeId] = 1;
970  proxyTreeIdx[nodeId] = proxyNodeIDs.size();
971  proxyNodeIDs.push_back(nodeId);
972  }else{
973  proxyNodeMap[nodeId]++;
974  }
975  }
976  proxyTreeNodeList &oneNATree = ptnTree; // spanning tree
977  int numNodesWithProxies = proxyNodeIDs.size();
978  oneNATree.resize(numNodesWithProxies);
979  //initialize oneNATree
980  for(int i=0; i<numNodesWithProxies; i++) {
981  proxyTreeNode *oneNode = &oneNATree.item(i);
982  delete [] oneNode->peIDs;
983  oneNode->nodeID = proxyNodeIDs[i];
984  oneNode->peIDs = new int[proxyNodeMap[oneNode->nodeID]];
985  oneNode->numPes = 0; //initially set to zero as used for incrementing later
986  }
987 
988  //set up the tree root which contains the home patch processor
989  proxyTreeNode *rootnode = &oneNATree.item(0);
990  rootnode->peIDs[0] = hpProcID;
991  rootnode->numPes++;
992 
993  for(int i=0; i<numProxies; i++) {
994  int procId = proxyList[i];
995  int nodeId = CkNodeOf(procId);
996  int idxInTree = proxyTreeIdx[nodeId];
997  CmiAssert(idxInTree>=0 && idxInTree<numNodesWithProxies);
998  proxyTreeNode *oneNode = &oneNATree.item(idxInTree);
999  oneNode->peIDs[oneNode->numPes] = procId;
1000  oneNode->numPes++;
1001  }
1002 }
1003 #else //branch of NODEAWARE_PROXY_SPANNINGTREE
1004 // only on PE 0
1005 void
1007 {
1008  CkPrintf("Info: build spanning tree with send: %d, recv: %d with branch factor %d\n",
1010 
1011  int i;
1012 
1013  processCpuLoad();
1014 
1015  int *numPatchesOnNode = new int[CkNumPes()];
1016  int numNodesWithPatches = 0;
1017  for (i=0; i<CkNumPes(); i++) numPatchesOnNode[i] = 0;
1018  int numPatches = PatchMap::Object()->numPatches();
1019  for (i=0; i<numPatches; i++) {
1020  int node = PatchMap::Object()->node(i);
1021  numPatchesOnNode[node]++;
1022  if (numPatchesOnNode[node] == 1)
1023  numNodesWithPatches ++;
1024  }
1025  int patchNodesLast =
1026  ( numNodesWithPatches < ( 0.7 * CkNumPes() ) );
1027  int *ntrees = new int[CkNumPes()];
1028  for (i=0; i<CkNumPes(); i++) ntrees[i] = 0;
1029  if (ptree.trees == NULL) ptree.trees = new NodeIDList[numPatches];
1030  for (int pid=0; pid<numPatches; pid++)
1031  {
1032  int numProxies = ptree.proxylist[pid].size();
1033  if (numProxies == 0) {
1034  //CkPrintf ("This is sheer evil!\n\n");
1035  //ProxyMgr::Object()->sendSpanningTreeToHomePatch(pid, NULL, 0);
1036  delete [] ntrees;
1037  delete [] numPatchesOnNode;
1038  return;
1039  }
1040  NodeIDList &tree = ptree.trees[pid]; // spanning tree
1041  NodeIDList oldtree; oldtree.swap(tree);
1042  tree.resize(numProxies+1);
1043  tree.setall(-1);
1044  tree[0] = PatchMap::Object()->node(pid);
1045  int s=1, e=numProxies;
1046  int nNonPatch = 0;
1047  int treesize = 1;
1048  int pp;
1049 
1050  // keep tree persistent for non-intermediate nodes
1051  for (pp=0; pp<numProxies; pp++) {
1052  int p = ptree.proxylist[pid][pp];
1053  int oldindex = oldtree.find(p);
1054  if (oldindex != -1 && oldindex <= numProxies) {
1055  int isIntermediate = (oldindex*proxySpanDim+1 <= numProxies);
1056  if (!isIntermediate) {
1057  tree[oldindex] = p;
1058  }
1059  else if (ntrees[p] < MAX_INTERNODE) {
1060  tree[oldindex] = p;
1061  ntrees[p] ++;
1062  }
1063  }
1064  }
1065 
1066  for (pp=0; pp<numProxies; pp++) {
1067  int p = ptree.proxylist[pid][pp]; // processor number
1068  if (tree.find(p) != -1) continue; // already used
1069  treesize++;
1070  if (patchNodesLast && numPatchesOnNode[p] ) {
1071  while (tree[e] != -1) { e--; if (e==-1) e = numProxies; }
1072  tree[e] = p;
1073  int isIntermediate = (e*proxySpanDim+1 <= numProxies);
1074  if (isIntermediate) ntrees[p]++;
1075  }
1076  else {
1077  while (tree[s] != -1) { s++; if (s==numProxies+1) s = 1; }
1078  int isIntermediate = (s*proxySpanDim+1 <= numProxies);
1079  if (isIntermediate && (ntrees[p] >= MAX_INTERNODE || noInterNode(p))) { // TOO MANY INTERMEDIATE TREES
1080  //if (isIntermediate && ntrees[p] >= MAX_INTERNODE) // TOO MANY INTERMEDIATE TREES
1081  while (tree[e] != -1) { e--; if (e==-1) e = numProxies; }
1082  tree[e] = p;
1083  isIntermediate = (e*proxySpanDim+1 <= numProxies);
1084  if (isIntermediate) ntrees[p]++;
1085  }
1086  else {
1087  tree[s] = p;
1088  nNonPatch++;
1089  if (isIntermediate) ntrees[p]++;
1090  }
1091  }
1092  }
1093  // send homepatch's proxy tree
1094  if(ptree.sizes)
1095  ptree.sizes[pid] = treesize;
1096  //ProxyMgr::Object()->sendSpanningTreeToHomePatch(pid, &tree[0], treesize);
1097  }
1098  /*for (i=0; i<CkNumPes(); i++) {
1099  if (ntrees[i] > MAX_INTERNODE) iout << "Processor " << i << "has (guess) " << ntrees[i] << " intermediate nodes." << endi;
1100  }*/
1101  delete [] ntrees;
1102  delete [] numPatchesOnNode;
1103 }
1104 #endif
1105 
1107 {
1108  int numPatches = PatchMap::Object()->numPatches();
1109  for (int pid=0; pid<numPatches; pid++) {
1110  int numProxies = ptree.proxylist[pid].size();
1111 #ifdef NODEAWARE_PROXY_SPANNINGTREE
1112  if (numProxies == 0)
1114  else {
1115  ProxyMgr::Object()->sendNodeAwareSpanningTreeToHomePatch(pid, ptree.naTrees[pid].begin(), ptree.naTrees[pid].size());
1116  }
1117 #else
1118  if (numProxies == 0)
1120  else {
1121  ProxyMgr::Object()->sendSpanningTreeToHomePatch(pid, ptree.trees[pid].begin(), ptree.trees[pid].size());
1122  }
1123 #endif
1124  }
1125 }
1126 
1127 void ProxyMgr::sendSpanningTreeToHomePatch(int pid, int *tree, int n)
1128 {
1129  CProxy_ProxyMgr cp(thisgroup);
1130  cp[PatchMap::Object()->node(pid)].recvSpanningTreeOnHomePatch(pid, tree, n);
1131 }
1132 
1133 void ProxyMgr::recvSpanningTreeOnHomePatch(int pid, int *tree, int n)
1134 {
1135  HomePatch *p = PatchMap::Object()->homePatch(pid);
1136  p->recvSpanningTree(tree, n);
1137 }
1138 
1140 {
1141  CProxy_ProxyMgr cp(thisgroup);
1143  cp[PatchMap::Object()->node(pid)].recvNodeAwareSpanningTreeOnHomePatch(msg);
1144 }
1145 
1147 {
1148  HomePatch *p = PatchMap::Object()->homePatch(msg->patch);
1149  p->recvNodeAwareSpanningTree(msg);
1150  delete msg;
1151 }
1152 
1153 void
1155  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1156  cp[msg->tree[0]].recvSpanningTree(msg);
1157 }
1158 
1160  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1161  int pe = msg->allPes[0]; //the root procID
1162 
1163 #if defined(PROCTRACE_DEBUG) && defined(NAST_DEBUG)
1164  DebugFileTrace *dft = DebugFileTrace::Object();
1165  dft->openTrace();
1166  dft->writeTrace("PMgr::sndST: from proc %d for patch[%d]\n", pe, msg->patch);
1167  dft->closeTrace();
1168 #endif
1169 
1170  cp[pe].recvNodeAwareSpanningTree(msg);
1171 }
1172 
1173 void
1175  int size = msg->tree.size();
1176  int *child = new int[proxySpanDim];
1177  int nChild = 0;
1178  int i;
1179  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1180  for (i=0; i<proxySpanDim; i++) {
1181  if (size > i+1) { child[i] = msg->tree[i+1]; nChild++; }
1182  }
1183  if (!PatchMap::Object()->homePatch(msg->patch)) {
1184  proxy->setSpanningTree(msg->node, child, nChild);
1185  }
1186 
1187  // build subtree and pass down
1188  if (nChild > 0) {
1189 
1190  nodecount ++;
1191  //if (nodecount > MAX_INTERNODE)
1192  // iout << "Processor " << CkMyPe() << "has (actual) " << nodecount << " intermediate nodes." << endi;
1193 
1194 //CkPrintf("[%d] %d:(%d) %d %d %d %d %d\n", CkMyPe(), msg->patch, size, msg->tree[0], msg->tree[1], msg->tree[2], msg->tree[3], msg->tree[4]);
1195  NodeIDList *tree = new NodeIDList[proxySpanDim];
1196  int level = 1, index=1;
1197  int done = 0;
1198  while (!done) {
1199  for (int n=0; n<nChild; n++) {
1200  if (done) break;
1201  for (int j=0; j<level; j++) {
1202  if (index >= size) { done = 1; break; }
1203  tree[n].add(msg->tree[index]);
1204  index++;
1205  }
1206  }
1207  level *=proxySpanDim;
1208  }
1209 
1210  ProxyMgr *proxyMgr = ProxyMgr::Object();
1211  for (i=0; i<proxySpanDim; i++) {
1212  if (tree[i].size()) {
1214  cmsg->patch = msg->patch;
1215  cmsg->node = CkMyPe();
1216  cmsg->tree.copy(tree[i]); // copy data for thread safety
1217  proxyMgr->sendSpanningTree(cmsg);
1218  }
1219  }
1220 
1221  delete [] tree;
1222  }
1223 
1224  delete [] child;
1225  delete msg;
1226 }
1227 
1228 //The "msg" represents the subtree rooted at this proc
1230 #if defined(PROCTRACE_DEBUG) && defined(NAST_DEBUG)
1231  DebugFileTrace *dft = DebugFileTrace::Object();
1232  dft->openTrace();
1233  dft->writeTrace("PMgr::recvST0 for patch[%d] with #nodes=%d\n", msg->patch, msg->numNodesWithProxies);
1234  dft->closeTrace();
1235  msg->printOut("PMgr::recvST");
1236 #endif
1237 
1238  //This function is divided into three parts. The tree root is msg->allPes[0]
1239  //1. set up its own immediate childrens
1240  int treesize = msg->numNodesWithProxies; //at least include one as its internal procs
1241  int iNChild = msg->numPesOfNode[0]-1; //number of internal children
1242  int eNChild = treesize-1; //number of external children
1243 
1244  CmiAssert(treesize>0);
1245  //use the same way of computing children in HomePatch::setupChildrenFromProxySpanningTree
1246  eNChild = (proxySpanDim>eNChild)?eNChild:proxySpanDim;
1247  int iSlots = proxySpanDim-eNChild;
1248  if(iNChild>0) {
1249  if(iSlots==0){
1250  //at least having one internal child
1251  iNChild = 1;
1252  }else{
1253  iNChild = (iSlots>iNChild)?iNChild:iSlots;
1254  }
1255  }
1256  int numChild = iNChild + eNChild;
1257  if(numChild==0){
1258  //Indicating this proxy is a leaf in the spanning tree
1259  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1260  proxy->setSpanningTree(msg->procID, NULL, 0);
1261 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1262  //When using NODEPATCHMGR, the proc-level is a flat list attached to the node
1263  //while the node-level spanning tree obeys the branch factor.
1264  //As a result, when passing down spanning trees, if this proc is on the same node
1265  //of its parent, then the NodeProxyMgr has already been set by its parent. There's
1266  //no need resetting here. However, the nodeChildren attached to this proxy has
1267  //to be set to NULL. -Chao Mei
1268  int onSameNode = (CkMyNode() == CkNodeOf(msg->procID));
1269  //set up proxyInfo inside NodeProxyMgr
1270  if(!onSameNode && !PatchMap::Object()->homePatch(msg->patch)){
1271  //only when this processor contains a proxy patch of "msg->patch"
1272  //is the patch registeration in NodeProxyMgr needed,
1273  //and itself needs to be registered
1274  CProxy_NodeProxyMgr pm(CkpvAccess(BOCclass_group).nodeProxyMgr);
1275  NodeProxyMgr *npm = pm[CkMyNode()].ckLocalBranch();
1276  npm->registerPatch(msg->patch, msg->numPesOfNode[0], msg->allPes);
1277  }
1278  //set children in terms of node ids
1279  proxy->setSTNodeChildren(0, NULL);
1280 #endif
1281  delete msg;
1282  return;
1283  }
1284 
1285  nodecount++;
1286  //if (nodecount > MAX_INTERNODE)
1287  // iout << "Processor " << CkMyPe() << "has (actual) " << nodecount << " intermediate nodes." << endi;
1288 
1289  if(!PatchMap::Object()->homePatch(msg->patch)){
1290  //the home patch of this spanning tree has been already set
1291  //in HomePatch::setupChildrenFromProxySpanningTree, so we
1292  //only care about the children setup for proxy patches here
1293  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1294  ALLOCA(int,children,numChild);
1295  //add external children
1296  int *p = msg->allPes + msg->numPesOfNode[0];
1297  for(int i=0; i<eNChild; i++) {
1298  children[i] = *p;
1299  p += msg->numPesOfNode[i+1];
1300  }
1301  //add internal children
1302  for(int i=eNChild, j=1; i<numChild; i++, j++) {
1303  children[i] = msg->allPes[j];
1304  }
1305  proxy->setSpanningTree(msg->procID, children, numChild);
1306 
1307 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1308  int onSameNode = (CkMyNode() == CkNodeOf(msg->procID));
1309  if(!onSameNode) {
1310  //set up proxyInfo inside NodeProxyMgr
1311  CProxy_NodeProxyMgr pm(CkpvAccess(BOCclass_group).nodeProxyMgr);
1312  NodeProxyMgr *npm = pm[CkMyNode()].ckLocalBranch();
1313  npm->registerPatch(msg->patch, msg->numPesOfNode[0], msg->allPes);
1314 
1315  //set children in terms of node ids
1316  ALLOCA(int,nodeChildren,eNChild+1);
1317  p = msg->allPes + msg->numPesOfNode[0];
1318  for(int i=0; i<eNChild; i++) {
1319  nodeChildren[i] = CkNodeOf(*p);
1320  p += msg->numPesOfNode[i+1];
1321  }
1322  //the last entry always stores the node id that contains this proxy
1323  nodeChildren[eNChild] = CkNodeOf(msg->allPes[0]);
1324  proxy->setSTNodeChildren(eNChild+1, nodeChildren);
1325  } else {
1326  proxy->setSTNodeChildren(0, NULL);
1327  }
1328 #endif
1329  }
1330 
1331  //2. send msgs for the tree to children proxies
1332  ResizeArray<int> *exTreeChildSize = new ResizeArray<int>[numChild];
1333  ResizeArray<int *> *exTreeChildPtr = new ResizeArray<int *>[numChild];
1334 
1335  //2a. first processing children of external nodes
1336  if(eNChild > 0) {
1337  int nodesToCnt = 1; //the number of children each root (current root's
1338  //immedidate external nodes) has in each level
1339  int pos = 1; //track the iteration over msg->numPesOfNode and skip the current root
1340  int *pePtr = msg->allPes + msg->numPesOfNode[0];
1341  int done = 0;
1342  while(!done) {
1343  for(int childID=0; childID<eNChild; childID++) {
1344  //iterate nodes on each level
1345  for(int i=0; i<nodesToCnt; i++) {
1346  int cursize = msg->numPesOfNode[pos];
1347  exTreeChildSize[childID].add(cursize);
1348  exTreeChildPtr[childID].add(pePtr);
1349  pos++;
1350  pePtr += cursize;
1351  if(pos==msg->numNodesWithProxies) {
1352  done = 1;
1353  break;
1354  }
1355  }
1356  if(done) break;
1357  }
1358  nodesToCnt *= proxySpanDim;
1359  }
1360  }
1361 
1362  //2b. secondly processing children on the same node
1363  if(iNChild>0) {
1364  int nodesToCnt = 1; //the number of children each root (current root's
1365  //immedidate internal child proxies) has in each level
1366  int pos = 1; //track the iteration over proxies on the same node and skip the current root
1367  int *pePtr = msg->allPes+1; //skip the root
1368  int done = 0;
1369  while(!done) {
1370  for(int childID=eNChild; childID<numChild; childID++) {
1371  //iterate nodes on each level
1372  for(int i=0; i<nodesToCnt; i++) {
1373  exTreeChildSize[childID].add(1);
1374  exTreeChildPtr[childID].add(pePtr);
1375  pos++;
1376  pePtr++;
1377  if(pos==msg->numPesOfNode[0]) {
1378  done = 1;
1379  break;
1380  }
1381  }
1382  if(done) break;
1383  }
1384  nodesToCnt *= proxySpanDim;
1385  }
1386  }
1387 
1388  for(int i=0; i<numChild; i++) {
1389  ResizeArray<int> *allSizes = &exTreeChildSize[i];
1390  ResizeArray<int *> *allPtrs = &exTreeChildPtr[i];
1391  int totalNodes = allSizes->size();
1392  int totalPes = 0;
1393  for(int j=0; j<totalNodes; j++) totalPes += allSizes->item(j);
1394  ProxyNodeAwareSpanningTreeMsg *cmsg = new(totalNodes, totalPes, 0) ProxyNodeAwareSpanningTreeMsg;
1395  cmsg->patch = msg->patch;
1396  cmsg->procID = CkMyPe();
1397  cmsg->numNodesWithProxies = totalNodes;
1398  int *pAllPes = cmsg->allPes;
1399  for(int j=0; j<totalNodes; j++) {
1400  int numPes = allSizes->item(j);
1401  cmsg->numPesOfNode[j] = numPes;
1402  memcpy(pAllPes, allPtrs->item(j), sizeof(int)*numPes);
1403  pAllPes += numPes;
1404  }
1405  #if defined(PROCTRACE_DEBUG) && defined(NAST_DEBUG)
1406  cmsg->printOut("sndChi:");
1407  #endif
1409  }
1410  delete [] exTreeChildSize;
1411  delete [] exTreeChildPtr;
1412  delete msg;
1413 }
1414 
1415 void ProxyMgr::recvNodeAwareSTParent(int patch, int parent){
1416 #if defined(PROCTRACE_DEBUG) && defined(NAST_DEBUG)
1417  DebugFileTrace *dft = DebugFileTrace::Object();
1418  dft->openTrace();
1419  dft->writeTrace("PMgr::recvSTParent: for ProxyPatch[%d], parent is %d\n", patch, parent);
1420  dft->closeTrace();
1421 #endif
1422  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(patch);
1423  CmiAssert(proxy!=NULL);
1424  proxy->setSpanningTree(parent, NULL, 0);
1425 }
1426 
1428  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1429  NodeID node = PatchMap::Object()->node(msg->patch);
1430  CmiEnableUrgentSend(1);
1431  cp[node].recvResults(msg);
1432  CmiEnableUrgentSend(0);
1433 }
1434 
1436  HomePatch *home = PatchMap::Object()->homePatch(msg->patch);
1437  home->receiveResults(msg); // delete done in HomePatch::receiveResults()
1438 }
1439 
1441  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1442  NodeID node = PatchMap::Object()->node(msg->patch);
1443  CmiEnableUrgentSend(1);
1444  cp[node].recvResults(msg);
1445  CmiEnableUrgentSend(0);
1446 }
1447 
1449  HomePatch *home = PatchMap::Object()->homePatch(msg->patch);
1450  home->receiveResults(msg); // delete done in HomePatch::receiveResults()
1451 }
1452 
1453 //sendResults is a direct function call, not an entry method
1455  ProxyPatch *patch = (ProxyPatch *)PatchMap::Object()->patch(msg->patch);
1456  ProxyCombinedResultMsg *ocMsg = patch->depositCombinedResultMsg(msg);
1457  if (ocMsg) {
1459  int destPe = patch->getSpanningTreeParent();
1460  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1461  CmiAssert(destPe!=CkMyPe());
1462  //if(destPe != CkMyPe()) {
1463 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1464  /*CkPrintf("ready to call node::recvImmRes on pe[%d] to dest[%d]\n", CkMyPe(), destPe);
1465  fflush(stdout);*/
1466 
1467  cMsg->destPe = destPe;
1468  CProxy_NodeProxyMgr cnp(CkpvAccess(BOCclass_group).nodeProxyMgr);
1469  cnp[CkNodeOf(destPe)].recvImmediateResults(cMsg);
1470 #else
1471  cp[destPe].recvImmediateResults(cMsg);
1472 #endif
1473  //}
1474  //else{
1476  // cp[destPe].recvResults(cMsg);
1477  //}
1478  }
1479 }
1480 
1482  ProxyCombinedResultRawMsg *msg = omsg;
1483 
1484 //Chao Mei: hack for QD in case of SMP with immediate msg
1485 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR) && (CMK_SMP) && defined(NAMDSRC_IMMQD_HACK)
1486  if(proxyRecvSpanning && msg->isFromImmMsgCall){
1487 // CkPrintf("qdcreate called on pe[%d]\n", CkMyPe());
1488 // fflush(stdout);
1489  //To compensate for the counter loss for message creation
1490  //inside the process of immediate message on comm thread
1491  CkpvAccess(_qd)->create();
1492  }
1493 #endif
1494 
1495  HomePatch *home = PatchMap::Object()->homePatch(msg->patch);
1496  if (home) {
1497  //printf("Home got a message\n");
1498  home->receiveResults(msg); // delete done in HomePatch::receiveResults()
1499  }
1500  else {
1501  NAMD_bug("ProxyMgr should receive result message on home processor");
1502  }
1503 }
1504 
1506  HomePatch *home = PatchMap::Object()->homePatch(omsg->patch);
1507  if (home) {
1508  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1509  CmiEnableUrgentSend(1);
1510  cp[CkMyPe()].recvResults(omsg);
1511  CmiEnableUrgentSend(0);
1512  }
1513  else {
1514  ProxyPatch *patch = (ProxyPatch *)PatchMap::Object()->patch(omsg->patch);
1516  if (ocMsg) {
1517  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1519  cp[patch->getSpanningTreeParent()].recvImmediateResults(cMsg);
1520  }
1521  }
1522 }
1523 
1525  ProxyCombinedResultRawMsg *msg = omsg;
1526 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1527  //CkPrintf("recvImmRes called on comm thread%d pe[%d]\n", CkMyRank()==CmiMyNodeSize(), CkMyPe());
1528  //fflush(stdout);
1529 
1530  int destRank = CkRankOf(msg->destPe);
1531  PatchMap *pmap = localPatchMaps[destRank];
1532  HomePatch *home = pmap->homePatch(msg->patch);
1533  if (home) {
1534 #if CMK_SMP && defined(NAMDSRC_IMMQD_HACK)
1535  msg->isFromImmMsgCall = (CkMyRank()==CkMyNodeSize());
1536 #endif
1537  CProxy_ProxyMgr cp(localProxyMgr);
1538  CmiEnableUrgentSend(1);
1539  cp[msg->destPe].recvResults(msg);
1540  CmiEnableUrgentSend(0);
1541 /*
1542  char *srcfrom = "Isfrom";
1543  if(CkMyRank()!=CmiMyNodeSize()) srcfrom="Notfrom";
1544  CkPrintf("%s comm thread from pe[%d]\n", srcfrom, CkMyPe());
1545  fflush(stdout);
1546 */
1547  }
1548  else {
1549  ProxyPatch *patch = (ProxyPatch *)pmap->patch(msg->patch);
1551  if (ocMsg) {
1552  CProxy_NodeProxyMgr cnp(thisgroup);
1553  ocMsg->destPe = patch->getSpanningTreeParent();
1555  cnp[CkNodeOf(cMsg->destPe)].recvImmediateResults(cMsg);
1556  }
1557  }
1558 #endif
1559 }
1560 
1561 void
1562 ProxyMgr::sendProxyData(ProxyDataMsg *msg, int pcnt, int *pids) {
1563 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1564  if(proxySendSpanning == 1) {
1565  CProxy_NodeProxyMgr cnp(CkpvAccess(BOCclass_group).nodeProxyMgr);
1566  for(int i=0; i<pcnt-1; i++) {
1567  ProxyDataMsg *copymsg = (ProxyDataMsg *)CkCopyMsg((void **)&msg);
1568  cnp[pids[i]].recvImmediateProxyData(copymsg);
1569  }
1570  cnp[pids[pcnt-1]].recvImmediateProxyData(msg);
1571  return;
1572  }
1573 #endif
1574  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1575  cp.recvImmediateProxyData(msg,pcnt,pids);
1576 }
1577 
1578 void
1580 //Chao Mei: hack for QD in case of SMP with immediate msg
1581 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR) && (CMK_SMP) && defined(NAMDSRC_IMMQD_HACK)
1582  if(proxySendSpanning && msg->isFromImmMsgCall){
1583 // CkPrintf("qdcreate called on pe[%d]\n", CkMyPe());
1584 // fflush(stdout);
1585  //To compensate for the counter loss for message creation
1586  //inside the process of immediate message on comm thread
1587  CkpvAccess(_qd)->create();
1588  }
1589 #endif
1590  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1591  proxy->receiveData(msg); // deleted in ProxyPatch::receiveAtoms()
1592 }
1593 
1594 void
1596  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1597  if (proxySendSpanning == 1) {
1598  // copy the message and send to spanning children
1599  //int *pids = (int*)alloca(proxy->getSpanningTreeNChild()*sizeof(int));
1600  //int npid = proxy->getSpanningTreeChild(pids);
1601  int npid = proxy->getSpanningTreeNChild();
1602  int *pids = (int *)proxy->getSpanningTreeChildPtr();
1603  if (npid) {
1604  ProxyDataMsg *newmsg = (ProxyDataMsg *)CkCopyMsg((void **)&msg);
1605 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1606  int ntreephs;
1607  PersistentHandle *treephs = proxy->getSpanningTreePhs(ntreephs);
1608  CmiAssert(treephs && ntreephs == npid);
1609  CmiUsePersistentHandle(treephs, ntreephs);
1610 #endif
1611  ProxyMgr::Object()->sendProxyData(newmsg,npid,pids);
1612 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1613  CmiUsePersistentHandle(NULL, 0);
1614 #endif
1615  #if 0
1616  //ChaoMei: buggy code??? the spanning tree doesn't always have 2 levels
1617  //At the second level of the tree immediate messages are not needed
1618  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1619  cp.recvProxyData(newmsg,npid,pids);
1620  #endif
1621  }
1622  }
1623  /* send to self via EP method to preserve priority */
1624  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1625  cp[CkMyPe()].recvProxyData(msg);
1626 }
1627 
1629 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1630  CProxy_ProxyMgr cp(localProxyMgr);
1631  proxyTreeNode *ptn = proxyInfo[msg->patch];
1632  CmiAssert(ptn->numPes!=0);
1633 
1634  //re-send msg to this nodes's children nodes.
1635  //only the first pe of a node of node-aware ST should contain children nodes
1636  int rank = CkRankOf(ptn->peIDs[0]);
1637  PatchMap *pmap = localPatchMaps[rank];
1638  ProxyPatch *ppatch = (ProxyPatch *)pmap->patch(msg->patch);
1639 
1640  int npid = ppatch->getSTNNodeChild();
1641  int *pids = ppatch->getSTNodeChildPtr();
1642  if(npid>0) {
1643  //only needs to send to other nodes, so check the last entry of pids.
1644  //This is because the data for proxies on the same node have been sent
1645  //later in this function by NodeProxyMgr.
1646  if(pids[npid-1]==CkMyNode()) npid--;
1647  }
1648  CProxy_NodeProxyMgr cnp(thisgroup);
1649 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1650  if (npid) {
1651  int ntreephs;
1652  PersistentHandle *treephs = ppatch->getSpanningTreePhs(ntreephs);
1653  CmiAssert(treephs && ntreephs >= npid);
1654  CmiUsePersistentHandle(treephs, ntreephs);
1655  }
1656 #endif
1657  for(int i=0; i<npid; i++) {
1658  ProxyDataMsg *copymsg = (ProxyDataMsg *)CkCopyMsg((void **)&msg);
1659  cnp[pids[i]].recvImmediateProxyData(copymsg);
1660  }
1661 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1662  CmiUsePersistentHandle(NULL, 0);
1663 #endif
1664 
1665  //re-send msg to it's internal cores
1666 #if CMK_SMP && defined(NAMDSRC_IMMQD_HACK)
1667  msg->isFromImmMsgCall = (CkMyRank()==CkMyNodeSize());
1668 #endif
1669  cp.recvProxyData(msg, ptn->numPes, ptn->peIDs);
1670 #else
1671  CkAbort("Bad execution path to NodeProxyMgr::recvImmediateProxyData\n");
1672 #endif
1673 }
1674 
1675 void
1676 ProxyMgr::sendProxyAll(ProxyDataMsg *msg, int pcnt, int *pids) {
1677 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1678  if(proxySendSpanning == 1) {
1679  CProxy_NodeProxyMgr cnp(CkpvAccess(BOCclass_group).nodeProxyMgr);
1680  for(int i=0; i<pcnt-1; i++) {
1681  ProxyDataMsg *copymsg = (ProxyDataMsg *)CkCopyMsg((void **)&msg);
1682  cnp[pids[i]].recvImmediateProxyAll(copymsg);
1683  }
1684  cnp[pids[pcnt-1]].recvImmediateProxyAll(msg);
1685  return;
1686  }
1687 #endif
1688  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1689  cp.recvImmediateProxyAll(msg,pcnt,pids);
1690 }
1691 
1692 void
1694 //Chao Mei: hack for QD in case of SMP with immediate msg
1695 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR) && (CMK_SMP) && defined(NAMDSRC_IMMQD_HACK)
1696  if(proxySendSpanning && msg->isFromImmMsgCall){
1697 // CkPrintf("qdcreate called on pe[%d]\n", CkMyPe());
1698 // fflush(stdout);
1699  //To compensate for the counter loss for message creation
1700  //inside the process of immediate message on comm thread
1701  CkpvAccess(_qd)->create();
1702  }
1703 #endif
1704 
1705  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1706  proxy->receiveAll(msg); // deleted in ProxyPatch::receiveAtoms()
1707 }
1708 
1709 void
1711  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1712  #if defined(PROCTRACE_DEBUG) && defined(NAST_DEBUG)
1713  DebugFileTrace *dft = DebugFileTrace::Object();
1714  dft->openTrace();
1715  dft->writeTrace("PMgr::recvImmPAll for patch[%d]\n", msg->patch);
1716  CmiAssert(proxy!=NULL);
1717  dft->writeTrace("PMgr::recvImmPAll assertion OK for patch[%d]\n", msg->patch);
1718  dft->closeTrace();
1719  #endif
1720  if (proxySendSpanning == 1) {
1721  // copy the message and send to spanning children
1722  //int *pids = (int*)alloca(proxy->getSpanningTreeNChild()*sizeof(int));
1723  //int npid = proxy->getSpanningTreeChild(pids);
1724  int npid = proxy->getSpanningTreeNChild();
1725  int *pids = (int *)proxy->getSpanningTreeChildPtr();
1726  if (npid) {
1727  ProxyDataMsg *newmsg = (ProxyDataMsg *)CkCopyMsg((void **)&msg);
1728 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1729  int ntreephs;
1730  PersistentHandle *treephs = proxy->getSpanningTreePhs(ntreephs);
1731  CmiAssert(treephs && ntreephs == npid);
1732  CmiUsePersistentHandle(treephs, ntreephs);
1733 #endif
1734  ProxyMgr::Object()->sendProxyAll(newmsg,npid,pids);
1735 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1736  CmiUsePersistentHandle(NULL, 0);
1737 #endif
1738  }
1739  }
1740  /* send to self via EP method to preserve priority */
1741  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1742  cp[CkMyPe()].recvProxyAll(msg);
1743 }
1744 
1746 #if defined(NODEAWARE_PROXY_SPANNINGTREE) && defined(USE_NODEPATCHMGR)
1747  CProxy_ProxyMgr cp(localProxyMgr);
1748  proxyTreeNode *ptn = proxyInfo[msg->patch];
1749  CmiAssert(ptn->numPes!=0);
1750  #if defined(PROCTRACE_DEBUG) && defined(NAST_DEBUG)
1751  //This could be executed on comm thd.
1752  printf("NodePMgr::recvImmPAll for patch[%d] on node %d rank %d, prepare to send proc ", msg->patch, CkMyNode(), CkMyRank());
1753  for(int i=0; i<ptn->numPes; i++) {
1754  printf("%d, ", ptn->peIDs[i]);
1755  }
1756  printf("\n");
1757  fflush(stdout);
1758  #endif
1759 
1760  //re-send msg to this nodes's children nodes.
1761  //only the first pe of a node of node-aware ST should contain children nodes
1762  int rank = CkRankOf(ptn->peIDs[0]);
1763  PatchMap *pmap = localPatchMaps[rank];
1764  ProxyPatch *ppatch = (ProxyPatch *)pmap->patch(msg->patch);
1765 
1766  int npid = ppatch->getSTNNodeChild();
1767  int *pids = ppatch->getSTNodeChildPtr();
1768  if(npid>0) {
1769  //only needs to send to other nodes, so check the last entry of pids.
1770  //This is because the data for proxies on the same node have been sent
1771  //later in this function by NodeProxyMgr.
1772  if(pids[npid-1]==CkMyNode()) npid--;
1773  }
1774 
1775 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1776  if (npid) {
1777  int ntreephs;
1778  PersistentHandle *treephs = ppatch->getSpanningTreePhs(ntreephs);
1779  CmiAssert(treephs && ntreephs >= npid);
1780  CmiUsePersistentHandle(treephs, ntreephs);
1781  }
1782 #endif
1783  CProxy_NodeProxyMgr cnp(thisgroup);
1784  for(int i=0; i<npid; i++) {
1785  ProxyDataMsg *copymsg = (ProxyDataMsg *)CkCopyMsg((void **)&msg);
1786  cnp[pids[i]].recvImmediateProxyAll(copymsg);
1787  }
1788 #if CMK_PERSISTENT_COMM && USE_PERSISTENT_TREE
1789  CmiUsePersistentHandle(NULL, 0);
1790 #endif
1791 
1792  //re-send msg to it's internal cores
1793 #if CMK_SMP && defined(NAMDSRC_IMMQD_HACK)
1794  msg->isFromImmMsgCall = (CkMyRank()==CkMyNodeSize());
1795 #endif
1796  cp.recvProxyAll(msg, ptn->numPes, ptn->peIDs);
1797 #else
1798  CkAbort("Bad execution path to NodeProxyMgr::recvImmediateProxyData\n");
1799 #endif
1800 }
1801 
1802 void ProxyMgr::printProxySpanningTree(){
1803 #ifdef NODEAWARE_PROXY_SPANNINGTREE
1804  int numPatches = PatchMap::Object()->numPatches();
1805  for(int i=0; i<numPatches; i++) {
1806  proxyTreeNodeList &oneList = ptree.naTrees[i];
1807  printf("ST tree for HomePatch[%d]: #nodes = %d\n", i, oneList.size());
1808  if(ptree.proxylist[i].size()==0) continue;
1809  printf("===%d=== pes/node: ", i);
1810  for(int j=0; j<oneList.size(); j++) {
1811  printf("%d ", oneList.item(j).numPes);
1812  }
1813  printf("\n");
1814  printf("===%d=== pe ids: ", i);
1815  for(int j=0; j<oneList.size(); j++) {
1816  for(int k=0; k<oneList.item(j).numPes; k++) {
1817  printf("%d ", oneList.item(j).peIDs[k]);
1818  }
1819  }
1820  printf("\n");
1821  }
1822  fflush(stdout);
1823 #else
1824  int numPatches = PatchMap::Object()->numPatches();
1825  for(int i=0; i<numPatches; i++) {
1826  NodeIDList &oneList = ptree.trees[i];
1827  printf("ST tree for HomePatch[%d]: #nodes = %d\n", i, oneList.size());
1828  if(ptree.proxylist[i].size()==0) continue;
1829  printf("===%d=== pe ids: ", i);
1830  for(int j=0; j<oneList.size(); j++) {
1831  printf("%d ", oneList.item(j));
1832  }
1833  printf("\n");
1834  }
1835  fflush(stdout);
1836 #endif
1837 }
1838 
1839 void NodeProxyMgr::registerPatch(int patchID, int numPes, int *pes){
1840  if(proxyInfo[patchID]) {
1841  delete proxyInfo[patchID];
1842  }
1843  if(numPes == 0) {
1844  proxyInfo[patchID] = NULL;
1845  }else{
1846  proxyInfo[patchID] = new proxyTreeNode(CkNodeOf(pes[0]),numPes,pes);
1847  }
1848 }
1849 
1851  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1852  NodeID node = PatchMap::Object()->node(msg->patch);
1853  CmiEnableUrgentSend(1);
1854  cp[node].recvResult(msg);
1855  CmiEnableUrgentSend(0);
1856 }
1858  HomePatch *homePatch = PatchMap::Object()->homePatch(msg->patch);
1859  homePatch->receiveResult(msg); // message deleted in registerProxy()
1860 }
1861 void ProxyMgr::recvData( ProxyGBISP2DataMsg *msg) { //hp -d> pp
1862  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1863  proxy->receiveData(msg); // deleted in ProxyPatch::receiveAtoms() ?
1864 }
1866  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
1867  NodeID node = PatchMap::Object()->node(msg->patch);
1868  CmiEnableUrgentSend(1);
1869  cp[node].recvResult(msg);
1870  CmiEnableUrgentSend(0);
1871 }
1873  HomePatch *homePatch = PatchMap::Object()->homePatch(msg->patch);
1874  homePatch->receiveResult(msg); // message deleted in registerProxy()
1875 }
1876 void ProxyMgr::recvData( ProxyGBISP3DataMsg *msg) { //hp -d> pp
1877  ProxyPatch *proxy = (ProxyPatch *) PatchMap::Object()->patch(msg->patch);
1878  proxy->receiveData(msg); // deleted in ProxyPatch::receiveAtoms() ?
1879 }
1880 
1882  //1. compute the total patches this node manages, and the total length of all proxy lists
1883  int totalPatches = 0;
1884  int totalProxies = 0;
1885  for(int i=0; i<bufSize; i++) {
1886  PatchProxyListMsg *one = bufs[i];
1887  totalPatches += one->numPatches;
1888  for(int j=0; j<one->numPatches; j++) totalProxies += one->proxyListLen[j];
1889  }
1890  totalPatches += size;
1891  for(int i=0; i<size; i++) {
1892  totalProxies += info[i].numProxies;
1893  }
1894 
1895  PatchProxyListMsg *msg = new(totalPatches, totalPatches, totalProxies, 0)PatchProxyListMsg(totalPatches);
1896  int msgPatchIdx = 0;
1897  int msgProxyPeIdx = 0;
1898  for(int i=0; i<bufSize; i++) {
1899  PatchProxyListMsg *one = bufs[i];
1900  int curPeIdx = 0;
1901  for(int j=0; j<one->numPatches; j++) {
1902  msg->patchIDs[msgPatchIdx] = one->patchIDs[j];
1903  int curListLen = one->proxyListLen[j];
1904  msg->proxyListLen[msgPatchIdx++] = curListLen;
1905  memcpy(msg->proxyPEs+msgProxyPeIdx, one->proxyPEs+curPeIdx, sizeof(int)*curListLen);
1906  curPeIdx += curListLen;
1907  msgProxyPeIdx += curListLen;
1908  }
1909  }
1910  for(int i=0; i<size; i++) {
1911  msg->patchIDs[msgPatchIdx] = info[i].patchID;
1912  int curListLen = info[i].numProxies;
1913  msg->proxyListLen[msgPatchIdx++] = curListLen;
1914  memcpy(msg->proxyPEs+msgProxyPeIdx, info[i].proxyList, sizeof(int)*curListLen);
1915  msgProxyPeIdx += curListLen;
1916  }
1917  return msg;
1918 }
1919 
1920 #define HOMEPATCH_TREE_BRFACTOR 2
1922  //We use implicit tree construction for all home patches
1923  std::vector<int> nodesWithPatches; //record the id of node that has home patches
1924  int myNodeIdx = -1; //the index into the above vector of this node
1925  for(int nodeId=0; nodeId<CkNumNodes(); ++nodeId) {
1926  int hpCnt = 0;
1927  int firstPe = CkNodeFirst(nodeId);
1928  int endPe = firstPe + CkNodeSize(nodeId);
1929  for(int pe=firstPe; pe < endPe; ++pe) {
1930  hpCnt += pmap->numPatchesOnNode(pe);
1931  }
1932  if(hpCnt==0) continue;
1933 
1934  nodesWithPatches.push_back(nodeId);
1935  if(CkMyNode() == nodeId) {
1936  //on my node
1937  myNodeIdx = nodesWithPatches.size()-1;
1938  numHomePatches = hpCnt;
1939  homepatchRecved = 0;
1940  localProxyLists = new ProxyListInfo[hpCnt];
1941  memset(localProxyLists, 0, sizeof(ProxyListInfo)*hpCnt);
1942  }
1943  }
1944 
1945  if(myNodeIdx==-1){
1946  //there's no home patches on this node
1947  //just set to a value that doesn't make sense in spanning tree.
1948  parentNode = -2;
1949  numKidNodes = 0;
1950  kidRecved = 0;
1951  return;
1952  }
1953 
1954  //calculate parent
1955  if(myNodeIdx == 0) {
1956  parentNode = -1;
1957  }else{
1958  int parentIdx = (myNodeIdx-1)/HOMEPATCH_TREE_BRFACTOR;
1959  parentNode = nodesWithPatches[parentIdx];
1960  }
1961 
1962  //calculate kids
1963  numKidNodes = 0;
1964  int totalNodes = nodesWithPatches.size();
1965  for(int i=1; i<=HOMEPATCH_TREE_BRFACTOR; i++) {
1966  int kidId = myNodeIdx*HOMEPATCH_TREE_BRFACTOR+i;
1967  if(kidId >= totalNodes) break;
1968  numKidNodes++;
1969  }
1970  if(numKidNodes!=0) {
1971  remoteProxyLists = new PatchProxyListMsg *[numKidNodes];
1972  }
1973  kidRecved = 0;
1974 
1975  //CkPrintf("Node[%d] has %d homepatches with parent=%d and %d kids \n", CkMyNode(), numHomePatches, parentNode, numKidNodes);
1976 }
1977 
1978 void NodeProxyMgr::sendProxyList(int pid, int *plist, int size){
1979  int insertIdx; //indexed from 0
1980  CmiLock(localDepositLock);
1981  insertIdx = homepatchRecved++; //ensure the atomic increment
1982 
1983  localProxyLists[insertIdx].patchID = pid;
1984  localProxyLists[insertIdx].numProxies = size;
1985  localProxyLists[insertIdx].proxyList = plist;
1986 
1987  if(insertIdx == (numHomePatches-1)) {
1988  //all local home patches have contributed
1990  }
1991  CmiUnlock(localDepositLock);
1992 }
1993 
1995  int insertIdx; //indexed from 0
1996  CmiLock(localDepositLock);
1997  insertIdx = kidRecved++;
1998 
1999  remoteProxyLists[insertIdx] = msg;
2000  if(insertIdx == (numKidNodes-1)) {
2001  //all kids have contributed;
2003  }
2004  CmiUnlock(localDepositLock);
2005 }
2006 
2008  if(homepatchRecved!=numHomePatches || kidRecved != numKidNodes) return;
2009 
2010  homepatchRecved = 0;
2011  kidRecved = 0;
2012  //construct the msg
2013  PatchProxyListMsg *msg = PatchProxyListMsg::createPatchProxyListMsg(remoteProxyLists, numKidNodes, localProxyLists, numHomePatches);
2014  if(parentNode == -1) {
2015  //send to proxy mgr on PE[0] as this is the root node
2016  CProxy_ProxyMgr cp(CkpvAccess(BOCclass_group).proxyMgr);
2017  cp[0].recvPatchProxyInfo(msg);
2018  }else{
2019  CProxy_NodeProxyMgr cnp(thisgroup);
2020  cnp[parentNode].sendProxyListInfo(msg);
2021  }
2022  for(int i=0; i<numKidNodes; i++) {
2023  delete remoteProxyLists[i];
2024  }
2025 }
2026 
2027 #include "ProxyMgr.def.h"
2028 
Elem * find(const Elem &elem)
Definition: UniqueSet.h:60
void copy(ResizeArray< Elem > &ra)
Definition: ResizeArray.h:59
static void * pack(ProxyResultMsg *msg)
void sendProxies()
Definition: HomePatch.C:509
std::ostream & iINFO(std::ostream &s)
Definition: InfoStream.C:81
void createProxies(void)
Definition: ProxyMgr.C:416
static ProxyResultVarsizeMsg * getANewMsg(NodeID nid, PatchID pid, int prioSize, ForceList *fls)
Definition: ProxyMgr.C:149
ProxyTree & getPtree()
Definition: ProxyMgr.C:384
int size(void) const
Definition: ResizeArray.h:131
void recvImmediateResults(ProxyCombinedResultRawMsg *)
Definition: ProxyMgr.C:1505
void setRecvSpanning()
Definition: ProxyMgr.C:370
void registerProxy(RegisterProxyMsg *)
Definition: HomePatch.C:443
int proxyRecvSpanning
Definition: ProxyMgr.C:45
int numComputes(void)
Definition: ComputeMap.h:101
ProxyMgr()
Definition: ProxyMgr.C:348
int getRecvSpanning()
Definition: ProxyMgr.C:375
void recvSpanningTree(ProxySpanningTreeMsg *)
Definition: ProxyMgr.C:1174
void sendSpanningTreeToHomePatch(int pid, int *tree, int n)
Definition: ProxyMgr.C:1127
double * cpuloads
Definition: NamdCentLB.C:24
void recvNodeAwareSTParent(int patch, int parent)
Definition: ProxyMgr.C:1415
static ProxyMgr * Object()
Definition: ProxyMgr.h:394
void recvProxyAll(ProxyDataMsg *)
Definition: ProxyMgr.C:1693
int flLen[Results::maxNumForces]
Definition: ProxyMgr.h:179
void clear(void)
Definition: UniqueSet.h:62
void createSTForHomePatches(PatchMap *pmap)
Definition: ProxyMgr.C:1921
static PatchMap * Object()
Definition: PatchMap.h:27
void sendProxies(int pid, int *list, int n)
Definition: ProxyMgr.C:599
void buildProxySpanningTree2()
Definition: ProxyMgr.C:576
ComputeType
Definition: ComputeMap.h:20
void recvImmediateResults(ProxyCombinedResultRawMsg *)
Definition: ProxyMgr.C:1524
static int * procidx
Definition: ProxyMgr.C:694
Definition: Vector.h:72
void sendNodeAwareSpanningTree(ProxyNodeAwareSpanningTreeMsg *)
Definition: ProxyMgr.C:1159
void basePatchIDList(int pe, PatchIDList &)
Definition: PatchMap.C:454
void recvNodeAwareSpanningTree(ProxyNodeAwareSpanningTreeMsg *msg)
Definition: HomePatch.C:671
void setSendSpanning()
Definition: ProxyMgr.C:361
#define DebugM(x, y)
Definition: Debug.h:75
static ProxyCombinedResultMsg * fromRaw(ProxyCombinedResultRawMsg *msg)
Definition: ProxyMgr.C:302
HomePatchList * homePatchList()
Definition: PatchMap.C:438
static void processCpuLoad()
Definition: ProxyMgr.C:712
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
BigReal z
Definition: Vector.h:74
int getSendSpanning()
Definition: ProxyMgr.C:366
void receiveAll(ProxyDataMsg *)
Definition: ProxyPatch.C:245
int upstreamNeighbors(int pid, PatchID *neighbor_ids)
Definition: PatchMap.C:669
void receiveResults(ProxyResultVarsizeMsg *msg)
Definition: HomePatch.C:837
void recvRegisterProxy(RegisterProxyMsg *)
Definition: ProxyMgr.C:532
ResizeArrayIter< T > begin(void) const
int add(const Elem &elem)
Definition: UniqueSet.h:52
int getSpanningTreeNChild(void)
Definition: ProxyPatch.h:36
#define iout
Definition: InfoStream.h:51
int numProxies
Definition: ProxyMgr.h:410
static double averageLoad
Definition: ProxyMgr.C:695
Patch * patch(PatchID pid)
Definition: PatchMap.h:244
HomePatch * homePatch(PatchID pid)
Definition: PatchMap.h:249
int add(const Elem &elem)
Definition: ResizeArray.h:101
static void outputProxyTree(ProxyTree &ptree, int np)
Definition: ProxyMgr.C:611
Definition: Patch.h:35
static ProxyCombinedResultRawMsg * toRaw(ProxyCombinedResultMsg *msg)
Definition: ProxyMgr.C:247
void resize(int i)
Definition: ResizeArray.h:84
UniqueSetIter< T > begin(void) const
Definition: UniqueSetIter.h:55
void setall(const Elem &elem)
Definition: ResizeArray.h:94
void unregisterPatch(PatchID pid, HomePatch *pptr)
Definition: PatchMap.C:796
static ProxyNodeAwareSpanningTreeMsg * getANewMsg(PatchID pid, NodeID nid, proxyTreeNode *tree, int size)
Definition: ProxyMgr.C:196
void unregisterProxy(PatchID pid)
Definition: ProxyMgr.C:538
NodeIDList tree
Definition: ProxyMgr.h:265
#define PRIORITY_SIZE
Definition: Priorities.h:13
int numPatches(void) const
Definition: PatchMap.h:59
void buildProxySpanningTree()
Definition: ProxyMgr.C:558
void unregisterProxy(UnregisterProxyMsg *)
Definition: HomePatch.C:457
ProxyCombinedResultMsg * depositCombinedResultRawMsg(ProxyCombinedResultRawMsg *)
Definition: ProxyPatch.C:540
ProxyPatch * proxyPatch
Definition: ProxyMgr.h:282
PatchID patch
Definition: ProxyMgr.h:66
void NAMD_bug(const char *err_msg)
Definition: common.C:195
int * sizes
Definition: ProxyMgr.h:298
ComputeType type(ComputeID cid)
Definition: ComputeMap.C:118
void recvImmediateProxyAll(ProxyDataMsg *)
Definition: ProxyMgr.C:1710
int inNodeProxySpanDim
Definition: ProxyMgr.C:48
int * proxyListLen
Definition: ProxyMgr.h:418
void recvNodeAwareSpanningTreeOnHomePatch(ProxyNodeAwareSpanningTreeMsg *msg)
Definition: ProxyMgr.C:1146
void removeUnusedProxies(void)
Definition: ProxyMgr.C:398
void receiveData(ProxyDataMsg *)
Definition: ProxyPatch.C:168
void homePatchIDList(PatchIDList &)
Definition: PatchMap.C:443
void recvResult(ProxyGBISP1ResultMsg *)
Definition: ProxyMgr.C:1857
PatchID patch
Definition: ProxyMgr.h:167
void recvProxies(int pid, int *list, int n)
Definition: ProxyMgr.C:633
void recvProxyData(ProxyDataMsg *)
Definition: ProxyMgr.C:1579
static PatchProxyListMsg * createPatchProxyListMsg(PatchProxyListMsg **bufs, int bufSize, ProxyListInfo *info, int size)
Definition: ProxyMgr.C:1881
~ProxyMgr()
Definition: ProxyMgr.C:355
void recvSpanningTree(int *t, int n)
Definition: HomePatch.C:677
void recvData(ProxyGBISP2DataMsg *)
Definition: ProxyMgr.C:1861
NodeIDList * trees
Definition: ProxyMgr.h:297
void recvSpanningTreeOnHomePatch(int pid, int *tree, int n)
Definition: ProxyMgr.C:1133
BigReal x
Definition: Vector.h:74
PatchID getPatchID() const
Definition: Patch.h:114
void buildSpanningTree0()
Definition: ProxyMgr.C:1006
#define ALLOCA(TYPE, NAME, SIZE)
Definition: ProxyMgr.C:42
#define ALIGN_8(x)
Definition: packmsg.h:25
void createProxy(PatchID pid)
Definition: ProxyMgr.C:492
void recvImmediateProxyAll(ProxyDataMsg *msg)
Definition: ProxyMgr.C:1745
UniqueSetIter< T > end(void) const
Definition: UniqueSetIter.h:64
int32 NodeID
Definition: NamdTypes.h:279
int32 nodeID
Definition: NamdTypes.h:317
ForceList * forceList[Results::maxNumForces]
Definition: ProxyMgr.h:254
#define HOMEPATCH_TREE_BRFACTOR
Definition: ProxyMgr.C:1920
Elem & item(int i)
Definition: ResizeArray.h:119
PatchID patch
Definition: ProxyMgr.h:97
void recvResults(ProxyResultVarsizeMsg *)
Definition: ProxyMgr.C:1435
void setSpanningTree(int, int *, int)
Definition: ProxyPatch.C:455
void sendProxyData(ProxyDataMsg *, int, int *)
Definition: ProxyMgr.C:1562
void sendSpanningTree(ProxySpanningTreeMsg *)
Definition: ProxyMgr.C:1154
int32 * peIDs
Definition: NamdTypes.h:318
void recvImmediateProxyData(ProxyDataMsg *)
Definition: ProxyMgr.C:1595
ProxyCombinedResultMsg * depositCombinedResultMsg(ProxyCombinedResultMsg *)
Definition: ProxyPatch.C:476
#define PACK_RESIZE(DATA)
Definition: packmsg.h:125
static int noInterNode(int p)
Definition: ProxyMgr.C:728
void printOut(char *tag)
Definition: ProxyMgr.C:217
void sendNodeAwareSpanningTreeToHomePatch(int pid, proxyTreeNode *tree, int n)
Definition: ProxyMgr.C:1139
void sendProxyList(int pid, int *plist, int size)
Definition: ProxyMgr.C:1978
iterator begin(void)
Definition: ResizeArray.h:36
void sendProxyAll(ProxyDataMsg *, int, int *)
Definition: ProxyMgr.C:1676
ForceList * forceList[Results::maxNumForces]
Definition: ProxyMgr.h:168
NodeID node
Definition: ProxyMgr.h:166
NodeIDList * proxylist
Definition: ProxyMgr.h:291
static ComputeMap * Object()
Definition: ComputeMap.h:89
iterator end(void)
Definition: ResizeArray.h:37
#define MAX_INTERNODE
Definition: ProxyMgr.C:608
void registerProxy(PatchID pid)
Definition: ProxyMgr.C:518
void sendResults(ProxyResultVarsizeMsg *)
Definition: ProxyMgr.C:1427
int find(const Elem &e) const
Definition: ResizeArray.h:141
BigReal y
Definition: Vector.h:74
int flLen[Results::maxNumForces]
Definition: ProxyMgr.h:233
#define PACK(DATA)
Definition: packmsg.h:123
void sendSpanningTrees()
Definition: ProxyMgr.C:1106
int getSpanningTreeParent()
Definition: ProxyPatch.h:33
void removeProxies(void)
Definition: ProxyMgr.C:388
int proxyMsgCount
Definition: ProxyMgr.h:290
void setProxyTreeBranchFactor(int dim)
Definition: ProxyMgr.C:379
int32 numPes
Definition: NamdTypes.h:319
const int * getSpanningTreeChildPtr()
Definition: ProxyPatch.h:35
void buildSpanningTree(void)
Definition: HomePatch.C:715
static int nodecount
Definition: ProxyMgr.h:398
int node(ComputeID cid)
Definition: ComputeMap.h:106
int numPids(ComputeID cid)
Definition: ComputeMap.C:101
int numPatchesOnNode(int node)
Definition: PatchMap.h:60
static ProxyResultMsg * unpack(void *ptr)
Definition: ProxyMgr.C:111
void receiveResult(ProxyGBISP1ResultMsg *msg)
Definition: HomePatch.C:5024
int pid(ComputeID cid, int i)
Definition: ComputeMap.C:107
static int compLoad(const void *a, const void *b)
Definition: ProxyMgr.C:697
void sendResult(ProxyGBISP1ResultMsg *)
Definition: ProxyMgr.C:1850
PACK_MSG(ProxySpanningTreeMsg, PACK(patch);PACK(node);PACK_RESIZE(tree);)
Definition: ProxyMgr.C:50
void registerPatch(PatchID pid, HomePatch *pptr)
Definition: PatchMap.C:786
void registerPatch(int patchID, int numPes, int *pes)
Definition: ProxyMgr.C:1839
int node(int pid) const
Definition: PatchMap.h:114
void swap(ResizeArray< Elem > &ra)
Definition: ResizeArray.h:64
int proxySpanDim
Definition: ProxyMgr.C:47
int del(const Elem &elem)
Definition: UniqueSet.h:56
void recvNodeAwareSpanningTree(ProxyNodeAwareSpanningTreeMsg *)
Definition: ProxyMgr.C:1229
void recvPatchProxyInfo(PatchProxyListMsg *msg)
Definition: ProxyMgr.C:658
int32 PatchID
Definition: NamdTypes.h:277
void removeProxy(PatchID pid)
Definition: ProxyMgr.C:507
ResizeArrayIter< T > end(void) const
int * proxyList
Definition: ProxyMgr.h:411
void contributeToParent()
Definition: ProxyMgr.C:2007
int numProxies()
Definition: ProxyMgr.h:396
void sendProxyListInfo(PatchProxyListMsg *msg)
Definition: ProxyMgr.C:1994
PatchProxyListMsg(int num)
Definition: ProxyMgr.h:422
void recvUnregisterProxy(UnregisterProxyMsg *)
Definition: ProxyMgr.C:552
void recvImmediateProxyData(ProxyDataMsg *msg)
Definition: ProxyMgr.C:1628
int proxySendSpanning
Definition: ProxyMgr.C:44