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