a50f94d261b7f5efa6d0ba02ed7ee3028e66e3b7
[namd.git] / src / NamdNborLB.C
1
2 #if !defined(WIN32) || defined(__CYGWIN__)
3 #include <unistd.h>
4 #endif
5 #include <fcntl.h>
6
7 #include "InfoStream.h"
8 #include "NamdNborLB.h"
9 #include "NamdNborLB.def.h"
10 #include "Node.h"
11 #include "PatchMap.h"
12 #include "ComputeMap.h"
13 #include "LdbCoordinator.h"
14
15 void CreateNamdNborLB()
16 {
17   // CkPrintf("[%d] creating NamdNborLB %d\n",CkMyPe(),loadbalancer);
18   CProxy_NamdNborLB::ckNew();
19   // CkPrintf("[%d] created NamdNborLB %d\n",CkMyPe(),loadbalancer);
20 }
21
22 NamdNborLB::NamdNborLB(): NeighborLB(CkLBOptions(-1))
23 {
24   //  if (CkMyPe()==0)
25   //   CkPrintf("[%d] NamdNborLB created\n",CkMyPe());
26   processorArray = 0;
27   patchArray = 0;
28   computeArray = 0;
29   act = 0;
30   ldbNum = 0;
31 }
32
33 /*
34 NamdNborLB::~NamdNborLB()
35 {
36   delete [] processorArray;
37   delete [] patchArray;
38   delete [] computeArray;
39 }
40 */
41
42 int NamdNborLB::max_neighbors() {
43   return 4;
44 }
45
46 int NamdNborLB::num_neighbors() {
47   return numNbors;
48 }
49
50 void NamdNborLB::neighbors(int* _n) {
51 #if 0
52     const int me = CkMyPe();
53     const int npe = CkNumPes();
54     if (npe > 1)
55       _n[0] = (me + npe - 1) % npe;
56     if (npe > 2)
57       _n[1] = (me + 1) % npe;
58
59     int bigstep = (npe - 1) / 3 + 1;
60     if (bigstep == 1) bigstep++;
61
62     if (npe > 3)
63       _n[2] = (me + bigstep) % npe;
64     if (npe > 4)
65       _n[3] = (me + npe - bigstep) % npe;
66 #else   // 2D mesh or Torus mesh
67 #define SEQ(x, y) ((x)*yDim + (y))
68 #define WRAP   0
69     numNbors = 0;
70     int yDim = (int)sqrt((double)CkNumPes());
71     int xDim = CkNumPes() / yDim;
72     if (CkNumPes() % yDim) xDim++;
73     int x = CkMyPe()/yDim;
74     int y = CkMyPe()%yDim;
75     int x1, y1, s;
76     // CmiPrintf("[%d]info: %d %d %d %d\n", CkMyPe(), xDim, yDim, x,y);
77
78     x1=x; y1 = y-1;
79 #if WRAP
80     if (y1==-1) y1=yDim-1;
81     if (SEQ(x1, y1) >= CkNumPes()) s = CkNumPes()-1;
82     else s = SEQ(x1, y1);
83     if (s != CkMyPe()) _n[numNbors++] = s;
84 #else
85     if (y1 != -1)  _n[numNbors++] = SEQ(x1, y1);
86 #endif
87
88     x1=x; y1=y+1;
89 #if WRAP
90     if (y1 == yDim || SEQ(x1,y1) >= CkNumPes()) y1=0;
91     s = SEQ(x1, y1);
92     if (s != _n[numNbors-1] && s != CkMyPe()) _n[numNbors++] = s;
93 #else
94     if (y1 == yDim || SEQ(x1,y1) >= CkNumPes()) ;
95     else _n[numNbors++] = SEQ(x1, y1);
96 #endif
97
98     y1=y; x1=x-1;
99 #if WRAP
100     if (x1==-1) x1=xDim-1;
101     if (SEQ(x1, y1) >= CkNumPes()) x1--;
102     s = SEQ(x1, y1);
103     if (s != CkMyPe()) _n[numNbors++] = s;
104 #else
105     if (x1!=-1) _n[numNbors++] = SEQ(x1, y1);
106 #endif
107
108     y1=y; x1=x+1;
109 #if WRAP
110     if (x1==xDim || SEQ(x1,y1) >= CkNumPes()) x1=0;
111     s = SEQ(x1, y1);
112     if (s != _n[numNbors-1] && s != CkMyPe()) _n[numNbors++] = s;
113 #else
114     if (x1==xDim || SEQ(x1,y1) >= CkNumPes()) ;
115     else _n[numNbors++] = SEQ(x1,y1);
116 #endif
117     // CmiPrintf("[%d] %d neighbors: %d %d %d %d\n", CkMyPe(), numNbors, _n[0], _n[1], _n[2], _n[3]);
118     act = (x+y)%2;
119 #endif
120
121 };
122
123 bool NamdNborLB::QueryBalanceNow(int _step)
124 {
125   // CkPrintf("[%d] QueryBalanceNow on step %d: %d\n",CkMyPe(),_step, LdbCoordinator::Object()->takingLdbData);
126   if ( LdbCoordinator::Object()->takingLdbData ) {
127     return true;
128   } else {
129     return false;
130   }
131 }
132
133 bool NamdNborLB::QueryMigrateStep(int _step)
134 {
135   // CmiPrintf("[%d] QueryMigrateStep %d %d.\n", CkMyPe(), _step, act);
136   return (act+ldbNum)%2 == 0;
137 }
138
139 NLBMigrateMsg* NamdNborLB::Strategy(NborBaseLB::LDStats* stats, int count)
140 {
141   //  CkPrintf("LDB:[%d] All statistics received at %f, %f\n",
142   //  CkMyPe(), CmiTimer(),CmiWallTimer());
143   int i,j;
144   int mype = CkMyPe();
145
146   ldbNum ++;
147
148   const int numProcessors = CkNumPes();
149   const int numPatches = PatchMap::Object()->numPatches();
150   const int numComputes = ComputeMap::Object()->numComputes();
151   const SimParameters* simParams = Node::Object()->simParameters;
152
153   int nMoveableComputes = 0;
154   for (i=0; i < count+1; i++) {
155     LDStats &thisLDStats = ((i==count)?myStats:stats[i]);
156     for (j=0; j < thisLDStats.n_objs; j++) {
157       const LDObjData &this_obj = thisLDStats.objData[j];
158       if (this_obj.omID().id.idx != 1) continue;
159       if (this_obj.id().id[1] == -2) continue;
160       if (this_obj.migratable)  nMoveableComputes++;
161     }
162   }
163   // CmiPrintf("%d nMoveableComputes: %d\n", CkMyPe(), nMoveableComputes);
164
165   // these sizes should never change
166   processorArray = new processorInfo[numProcessors];
167   patchArray = new patchInfo[numPatches];
168 //  if ( ! computeArray ) computeArray = new computeInfo[nMoveableComputes];
169   computeArray = new computeInfo[nMoveableComputes];
170
171   nMoveableComputes = buildData(stats,count);
172
173   //CmiPrintf("AlgNbor begin on %d\n", CkMyPe());
174   AlgNbor(mype, computeArray,patchArray,processorArray,
175                         nMoveableComputes, numPatches, numProcessors, count);
176   //CmiPrintf("AlgNbor end on %d\n", CkMyPe());
177
178   CkVec<MigrateInfo *> migrateInfo;
179   for(i=0;i<nMoveableComputes;i++) {
180     if (computeArray[i].oldProcessor == mype)
181     if (computeArray[i].processor != computeArray[i].oldProcessor) {
182       // CkPrintf("[%d] Obj %d migrating from %d to %d\n",
183       //          CkMyPe(),computeArray[i].handle.id.id[0],
184       //       computeArray[i].processor,computeArray[i].oldProcessor);
185       MigrateInfo *migrateMe = new MigrateInfo;
186       migrateMe->obj = computeArray[i].handle;
187       migrateMe->from_pe = computeArray[i].oldProcessor;
188       migrateMe->to_pe = computeArray[i].processor;
189       migrateInfo.insertAtEnd(migrateMe);
190     }
191   }
192   
193   int migrate_count=migrateInfo.length();
194   CkPrintf("NamdNborLB [%d] migrating %d elements\n", CkMyPe(), migrate_count);
195   NLBMigrateMsg* msg = new(migrate_count,CkNumPes(),CkNumPes(),0) NLBMigrateMsg;
196   msg->n_moves = migrate_count;
197   for(i=0; i < migrate_count; i++) {
198     MigrateInfo* item = migrateInfo[i];
199     msg->moves[i] = *item;
200     delete item;
201     migrateInfo[i] = 0;
202   }
203
204   delete [] patchArray;
205   delete [] computeArray;
206   /*
207   for(i=0; i<numProcessors; i++)
208       delete [] processorArray[i].proxyUsage;
209   */
210   delete [] processorArray;
211
212   return msg;
213 };
214
215
216 int NamdNborLB::buildData(NborBaseLB::LDStats* stats, int count)
217 {
218   PatchMap* patchMap = PatchMap::Object();
219   ComputeMap* computeMap = ComputeMap::Object();
220   double bg_weight = 0.7;
221
222   int i;
223   for (i=0; i<CkNumPes(); i++) {
224     processorArray[i].load = 0.0;
225     processorArray[i].backgroundLoad = 0.0;
226     processorArray[i].available = false;
227     if (i == CkMyPe()) {
228       processorArray[i].Id = i;
229       processorArray[i].available = myStats.move;
230     if (patchMap->numPatches() > 0)
231       processorArray[i].backgroundLoad = myStats.bg_walltime*bg_weight;
232     else 
233       processorArray[i].backgroundLoad = myStats.bg_walltime;
234       continue;
235     }
236     int peslot = NeighborIndex(i);
237     if (peslot != -1) {
238     processorArray[i].Id = i;
239       processorArray[i].available = stats[peslot].move;
240     if (patchMap->numPatches() > 0)
241       processorArray[i].backgroundLoad = bg_weight * stats[peslot].bg_walltime;
242     else 
243       processorArray[i].backgroundLoad = stats[peslot].bg_walltime;
244     }
245     else 
246       processorArray[i].Id = -2;
247   }
248
249   int nMoveableComputes=0;
250   int nProxies = 0;             // total number of estimated proxies
251   for (i=0; i<patchMap->numPatches(); i++) {
252         patchArray[i].Id = i;
253         patchArray[i].numAtoms = 0;
254         patchArray[i].processor = patchMap->node(i);
255         int neighborNodes[PatchMap::MaxOneAway + PatchMap::MaxTwoAway];
256         const int numProxies = requiredProxies(i,neighborNodes);
257         nProxies += numProxies;
258
259         for (int k=0; k<numProxies; k++) {
260           if (NeighborIndex(neighborNodes[k]) != -1) {
261             processorArray[neighborNodes[k]].proxies.unchecked_insert(&patchArray[i]);
262             patchArray[i].proxiesOn.unchecked_insert(&processorArray[neighborNodes[k]]);
263           }
264         }
265   }
266   for (i=0; i < count+1; i++) {
267     int j;
268     LDStats &thisLDStats = ((i==count)?myStats:stats[i]);
269     for (j=0; j < thisLDStats.n_objs; j++) {
270       const LDObjData &this_obj = thisLDStats.objData[j];
271       // filter out non-NAMD managed objects (like PME array)
272       if (this_obj.omID().id.idx != 1) continue;
273       if (this_obj.id().id[1] == -2) { // Its a patch
274 /*
275         const int pid = this_obj.id.id[0];
276         int neighborNodes[PatchMap::MaxOneAway + PatchMap::MaxTwoAway];
277
278         patchArray[pid].Id = pid;
279         patchArray[pid].numAtoms = 0;
280         patchArray[pid].processor = i;
281         const int numProxies = requiredProxies(pid,neighborNodes);
282         nProxies += numProxies;
283
284         for (int k=0; k<numProxies; k++) {
285           processorArray[neighborNodes[k]].proxies.unchecked_insert(&patchArray[pid]);
286           patchArray[pid].proxiesOn.unchecked_insert(&processorArray[neighborNodes[k]]);
287         }
288 */
289       } else if (this_obj.migratable) { // Its a compute
290         const int cid = this_obj.id().id[0];
291         const int p0 = computeMap->pid(cid,0);
292
293         // For self-interactions, just return the same pid twice
294         int p1;
295         if (computeMap->numPids(cid) > 1)
296           p1 = computeMap->pid(cid,1);
297         else p1 = p0;
298         computeArray[nMoveableComputes].Id = cid;
299         computeArray[nMoveableComputes].oldProcessor = thisLDStats.from_pe;
300         computeArray[nMoveableComputes].processor = -1;
301         computeArray[nMoveableComputes].patch1 = p0;
302         computeArray[nMoveableComputes].patch2 = p1;
303         computeArray[nMoveableComputes].handle = this_obj.handle;
304         computeArray[nMoveableComputes].load = this_obj.wallTime;
305         nMoveableComputes++;
306       }
307     }
308   }
309   return nMoveableComputes;
310 }
311
312 // Figure out which proxies we will definitely create on other
313 // nodes, without regard for non-bonded computes.  This code is swiped
314 // from ProxyMgr, and changes there probable need to be propagated here.
315
316 int NamdNborLB::requiredProxies(PatchID id, int neighborNodes[])
317 {
318   enum proxyHere { No, Yes };
319   int numNodes = CkNumPes();
320   proxyHere *proxyNodes = new proxyHere[numNodes];
321   int nProxyNodes;
322   int i;
323
324   // Note all home patches.
325   for ( i = 0; i < numNodes; ++i )
326   {
327     proxyNodes[i] = No;
328   }
329   nProxyNodes=0;
330
331   // Check all two-away neighbors.
332   // This is really just one-away neighbors, since 
333   // two-away always returns zero: RKB
334   PatchID neighbors[1 + PatchMap::MaxOneAway + PatchMap::MaxTwoAway];
335
336   PatchMap* patchMap = PatchMap::Object();
337
338   int myNode = patchMap->node(id);
339   neighbors[0] = id;
340   int numNeighbors = 1 + patchMap->downstreamNeighbors(id,neighbors+1);
341   for ( i = 0; i < numNeighbors; ++i )
342   {
343     const int proxyNode = patchMap->basenode(neighbors[i]);
344     if (proxyNode != myNode)
345       if (proxyNodes[proxyNode] == No)
346       {
347         proxyNodes[proxyNode] = Yes;
348         neighborNodes[nProxyNodes] = proxyNode;
349         nProxyNodes++;
350       }
351   }
352
353   delete [] proxyNodes;
354   return nProxyNodes;
355 }
356