a13ccf51cfdadbdb8b3a6c80cd30cf8bf7d516a6
[charm.git] / src / ck-com / ComlibStrategy.C
1 /**
2    @addtogroup CharmComlib
3    @{
4    @file
5    Implementations of ComlibStrategy.h
6 */
7
8 #include "ComlibStrategy.h"
9 #include "register.h"
10
11
12 void CharmStrategy::pup(PUP::er &p) {
13   //Strategy::pup(p);
14     p | nginfo;
15     p | ginfo;
16     p | ainfo;
17     //p | forwardOnMigration;
18     p | mflag;
19     p | onFinish;
20 }
21
22
23
24
25
26 /** 
27     Deliver a message to a set of indices using the array manager. Indices can be local or remote. 
28     
29     An optimization for [nokeep] methods is applied: the message is not copied for each invocation.
30    
31     @return the number of destination objects which were not local (information
32     retrieved from the array/location manager)
33 */
34 int CharmStrategy::deliverToIndices(void *msg, int numDestIdxs, const CkArrayIndexMax* indices ){
35   int count = 0;
36   
37   envelope *env = UsrToEnv(msg);
38   int ep = env->getsetArrayEp();
39   CkUnpackMessage(&env);
40
41   CkArrayID destination_aid = env->getsetArrayMgr();
42   CkArray *a=(CkArray *)_localBranch(destination_aid);
43
44   env->setPacked(0);
45   env->getsetArrayHops()=1;
46   env->setUsed(0);
47
48   //  CkPrintf("Delivering to %d objects\n", numDestIdxs);
49
50   if(numDestIdxs > 0){
51         
52     // SEND to all destination objects except the last one
53     for(int i=0; i<numDestIdxs-1;i++){
54       env->getsetArrayIndex() = indices[i];
55       
56       //      CkPrintf("[%d] in deliverToIndices env->event=%d pe=%d\n", CkMyPe(), (int)env->getEvent(), (int)env->getSrcPe());
57
58       if(_entryTable[ep]->noKeep)
59         // don't make a copy for [nokeep] entry methods
60         count += a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
61       else {
62         void *newmsg = CkCopyMsg(&msg);
63         count += a->deliver((CkArrayMessage *)newmsg, CkDeliver_queue);
64       }
65     }
66     
67     // SEND to the final destination object
68     env->getsetArrayIndex() = indices[numDestIdxs-1];
69     
70     if(_entryTable[ep]->noKeep){
71       count += a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
72       CmiFree(env); // runtime frees the [nokeep] messages
73     }
74     else {
75       count += a->deliver((CkArrayMessage *)msg, CkDeliver_queue);
76     }
77     
78   }
79
80   return count;
81 }
82
83
84
85
86
87
88
89
90 void CharmMessageHolder::pup(PUP::er &p) {
91
92     //    CkPrintf("In CharmMessageHolder::pup \n"); 
93
94     MessageHolder::pup(p);
95
96     //Sec ID depends on the message
97     //Currently this pup is only being used for remote messages
98     sec_id = NULL;
99 }
100
101 //PUPable_def(CharmStrategy);
102 PUPable_def(CharmMessageHolder);
103
104 ComlibNodeGroupInfo::ComlibNodeGroupInfo() {
105     isNodeGroup = 0;
106     ngid.setZero();
107 };
108
109 void ComlibNodeGroupInfo::pup(PUP::er &p) {
110     p | isNodeGroup;
111     p | ngid;
112 }
113
114 ComlibGroupInfo::ComlibGroupInfo() {
115     
116     isSrcGroup = 0;
117     isDestGroup = 0;
118     nsrcpes = 0;
119     ndestpes = 0;
120     srcpelist = NULL;
121     destpelist = NULL;
122     sgid.setZero();
123     dgid.setZero();
124 };
125
126 ComlibGroupInfo::~ComlibGroupInfo() {
127     if(nsrcpes > 0 && srcpelist != NULL)
128         delete [] srcpelist;
129
130     if(ndestpes > 0 && destpelist != NULL)
131         delete [] destpelist;
132 }
133
134 void ComlibGroupInfo::pup(PUP::er &p){
135
136     p | sgid;
137     p | dgid;
138     p | nsrcpes;
139     p | ndestpes;
140
141     p | isSrcGroup;
142     p | isDestGroup;
143
144     if(p.isUnpacking()) {
145         if(nsrcpes > 0) 
146             srcpelist = new int[nsrcpes];
147
148         if(ndestpes > 0) 
149             destpelist = new int[ndestpes];
150     }
151
152     if(nsrcpes > 0) 
153         p(srcpelist, nsrcpes);
154
155     if(ndestpes > 0) 
156         p(destpelist, ndestpes);
157 }
158
159 void ComlibGroupInfo::setSourceGroup(CkGroupID gid, int *pelist, 
160                                          int npes) {
161     this->sgid = gid;
162     srcpelist = pelist;
163     nsrcpes = npes;
164     isSrcGroup = 1;
165
166     if(nsrcpes == 0) {
167         nsrcpes = CkNumPes();
168         srcpelist = new int[nsrcpes];
169         for(int count =0; count < nsrcpes; count ++)
170             srcpelist[count] = count;
171     }
172 }
173
174 void ComlibGroupInfo::getSourceGroup(CkGroupID &gid, int *&pelist, 
175                                          int &npes){
176     gid = this->sgid;
177     npes = nsrcpes;
178
179     pelist = new int [nsrcpes];
180     memcpy(pelist, srcpelist, npes * sizeof(int));
181 }
182
183 void ComlibGroupInfo::getSourceGroup(CkGroupID &gid){
184     gid = this->sgid;
185 }
186
187 void ComlibGroupInfo::setDestinationGroup(CkGroupID gid, int *pelist, 
188                                          int npes) {
189     this->dgid = gid;
190     destpelist = pelist;
191     ndestpes = npes;
192     isDestGroup = 1;
193
194     if(ndestpes == 0) {
195         ndestpes = CkNumPes();
196         destpelist = new int[ndestpes];
197         for(int count =0; count < ndestpes; count ++)
198             destpelist[count] = count;
199     }
200 }
201
202 void ComlibGroupInfo::getDestinationGroup(CkGroupID &gid, int *&pelist, 
203                                          int &npes) {
204     gid = this->dgid;
205     npes = ndestpes;
206
207     pelist = new int [ndestpes];
208     memcpy(pelist, destpelist, npes * sizeof(int));
209 }
210
211 void ComlibGroupInfo::getDestinationGroup(CkGroupID &gid) {
212     gid = this->dgid;
213 }
214
215 int *ComlibGroupInfo::getCombinedCountList() {
216   int *result = new int[CkNumPes()];
217   int i;
218   for (i=0; i<CkNumPes(); ++i) result[i] = 0;
219   if (nsrcpes != 0) {
220     for (i=0; i<nsrcpes; ++i) result[srcpelist[i]] |= 1;
221   } else {
222     for (i=0; i<CkNumPes(); ++i) result[i] |= 1;
223   }
224   if (ndestpes != 0) {
225     for (i=0; i<ndestpes; ++i) result[destpelist[i]] |= 2;
226   } else {
227     for (i=0; i<CkNumPes(); ++i) result[i] |= 2;
228   }
229   return result;
230 }
231
232
233 ComlibArrayInfo::ComlibArrayInfo() {
234         
235     src_aid.setZero();
236     isAllSrc = 0;
237     totalSrc = 0;
238     isSrcArray = 0;
239
240     dest_aid.setZero();
241     isAllDest = 0;
242     totalDest = 0;
243     isDestArray = 0;
244 };
245
246
247 void ComlibArrayInfo::setSourceArray(CkArrayID aid, CkArrayIndexMax *e, int nind){
248     src_aid = aid;
249     isSrcArray = 1;
250
251     src_elements.removeAll();
252     for (int i=0; i<nind; ++i){
253       CkAssert(e[i].nInts == 1);
254       src_elements.push_back(e[i]);
255     }
256     
257     if (nind == 0) 
258         isAllSrc = 1;
259     else 
260         isAllSrc = 0;
261
262     totalSrc = nind;
263
264     CkAssert(src_elements.size() == totalSrc);    
265
266 }
267
268
269 void ComlibArrayInfo::setDestinationArray(CkArrayID aid, CkArrayIndexMax *e, int nind){
270   ComlibPrintf("[%d] ComlibArrayInfo::setDestinationArray  dest_elements\n", CkMyPe());
271     dest_aid = aid;
272     isDestArray = 1;
273    
274     dest_elements.removeAll();
275     for (int i=0; i<nind; ++i){
276       CkAssert(e[i].nInts > 0);
277       dest_elements.push_back(e[i]);
278     }
279
280     if (nind == 0) 
281         isAllDest = 1;
282     else 
283         isAllDest = 0;
284     
285     totalDest = nind;
286     CkAssert(dest_elements.size() == totalDest);    
287
288 }
289
290
291 /// @TODO fix the pup!
292 //Each strategy must define his own Pup interface.
293 void ComlibArrayInfo::pup(PUP::er &p){ 
294     p | src_aid;
295     p | isSrcArray;
296     p | isAllSrc;
297     p | totalSrc;
298     p | src_elements; 
299     p | new_src_elements;
300
301     p | dest_aid;
302     p | isDestArray;
303     p | isAllDest;
304     p | totalDest;
305     p | dest_elements; 
306     p | new_dest_elements;
307
308     if (p.isPacking() || p.isUnpacking()) {
309       // calling purge both during packing (at the end) and during unpacking
310       // allows this code to be executed both on processor 0 (where the object
311       // is created) and on every other processor where it arrives through PUP.
312       purge();
313     }
314
315     
316 }
317
318
319 void ComlibArrayInfo::printDestElementList() {
320   char buf[100000];
321   buf[0] = '\0';
322   for(int i=0;i<dest_elements.size();i++){
323     sprintf(buf+strlen(buf), " %d", dest_elements[i].data()[0]);
324   }
325   CkPrintf("[%d] dest_elements = %s\n", CkMyPe(), buf);
326 }
327
328
329 void ComlibArrayInfo::newElement(CkArrayID &id, const CkArrayIndex &idx) {
330   CkAbort("New Comlib implementation does not allow dynamic element insertion yet\n");
331   //  CkPrintf("ComlibArrayInfo::newElement dest_elements\n");
332   //  if (isAllSrc && id==src_aid) src_elements.push_back(idx);
333   //  if (isAllDest && id==dest_aid) dest_elements.push_back(idx);
334 }
335
336 void ComlibArrayInfo::purge() {
337   //    ComlibPrintf("[%d] ComlibArrayInfo::purge srcArray=%d (%d), destArray=%d (%d)\n",CkMyPe(),isSrcArray,isAllSrc,isDestArray,isAllDest);
338
339   if (isSrcArray) {
340     CkArray *a = (CkArray *)_localBranch(src_aid);
341
342     // delete all the source elements for which we are not homePe
343     for (int i=src_elements.size()-1; i>=0; --i) {
344       if (a->homePe(src_elements[i]) != CkMyPe()) {                     
345         ComlibPrintf("[%d] ComlibArrayInfo::purge removing home=%d src element %d  i=%d\n", CkMyPe(),a->homePe(src_elements[i]), src_elements[i].data()[0], i);
346         src_elements.remove(i); 
347       }
348     }
349   }
350
351   if (isDestArray) {
352     CkArray *a = (CkArray *)_localBranch(dest_aid);
353         
354     // delete all the destination elements for which we are not homePe
355     for (int i=dest_elements.size()-1; i>=0; --i) {
356       if (a->homePe(dest_elements[i]) != CkMyPe()) {
357         ComlibPrintf("[%d] ComlibArrayInfo::purge removing home=%d dest element %d  i=%d\n", CkMyPe(), a->homePe(dest_elements[i]), dest_elements[i].data()[0], i);
358         dest_elements.remove(i); 
359       }
360     }           
361   }
362
363 }
364
365 int *ComlibArrayInfo::getCombinedCountList() {
366   int *result = new int[CkNumPes()];
367   int i;
368   for (i=0; i<CkNumPes(); ++i) result[i] = 0;
369   CkArray *a = (CkArray *)_localBranch(src_aid);
370   if (src_elements.size() != 0) {
371     for (i=0; i<src_elements.size(); ++i) result[a->homePe(src_elements[i])] |= 1;
372   } else {
373     for (i=0; i<CkNumPes(); ++i) result[i] |= 1;
374   }
375   a = (CkArray *)_localBranch(dest_aid);
376   if (dest_elements.size() != 0) {
377     for (i=0; i<dest_elements.size(); ++i) result[a->homePe(dest_elements[i])] |= 2;
378   } else {
379     for (i=0; i<CkNumPes(); ++i) result[i] |= 2;
380   }
381   return result;
382 }
383
384 /*
385 //Get the list of destination processors
386 void ComlibArrayInfo::getDestinationPeList(int *&destpelist, int &ndestpes) {
387     
388     int count = 0, acount =0;
389     
390     //Destination has not been set
391     if(nDestIndices < 0) {
392         destpelist = 0;
393         ndestpes = 0;
394         return;
395     }
396
397     //Create an array of size CkNumPes()
398     //Inefficient in space
399     ndestpes = CkNumPes();
400     destpelist = new int[ndestpes];
401
402     memset(destpelist, 0, ndestpes * sizeof(int));    
403
404     if(nDestIndices == 0){
405         for(count =0; count < CkNumPes(); count ++) 
406             destpelist[count] = count;             
407         return;
408     }
409
410     ndestpes = 0;
411     CkArray *amgr = CkArrayID::CkLocalBranch(dest_aid);
412
413     //Find the last known processors of the array elements
414     for(acount = 0; acount < nDestIndices; acount++) {
415
416       //int p = ComlibGetLastKnown(dest_aid, dest_elements[acount]); 
417         int p = amgr->lastKnown(dest_elements[acount]);
418         
419         for(count = 0; count < ndestpes; count ++)
420             if(destpelist[count] == p)
421                 break;
422         
423         if(count == ndestpes) {
424             destpelist[ndestpes ++] = p; 
425         }       
426     }                            
427 }
428
429 void ComlibArrayInfo::getSourcePeList(int *&srcpelist, int &nsrcpes) {
430     
431     int count = 0, acount =0;
432
433     if(nSrcIndices < 0) {
434         srcpelist = 0;
435         nsrcpes = 0;
436         return;
437     }
438
439     nsrcpes = CkNumPes();
440     srcpelist = new int[nsrcpes];
441
442     memset(srcpelist, 0, nsrcpes * sizeof(int));    
443
444     if(nSrcIndices == 0){
445         for(count =0; count < CkNumPes(); count ++) 
446             srcpelist[count] = count;             
447         return;
448     }
449
450     nsrcpes = 0;
451     CkArray *amgr = CkArrayID::CkLocalBranch(src_aid);
452
453     for(acount = 0; acount < nSrcIndices; acount++) {
454         
455       //int p = ComlibGetLastKnown(src_aid, src_elements[acount]); 
456         int p = amgr->lastKnown(src_elements[acount]);
457         
458         for(count = 0; count < nsrcpes; count ++)
459             if(srcpelist[count] == p)
460                 break;
461         
462         if(count == nsrcpes) {
463             srcpelist[nsrcpes ++] = p; 
464         }       
465     }                            
466 }
467
468 void ComlibArrayInfo::getCombinedPeList(int *&pelist, int &npes) {
469
470     int count = 0;        
471     pelist = 0;
472     npes = 0;
473     
474     //Both arrays empty;
475     //Sanity check, this should really not happen
476     if(nSrcIndices < 0 && nDestIndices < 0) {
477         CkAbort("Arrays have not been set\n");
478         return;
479     }
480     
481     //One of them is the entire array Hence set the number of
482     //processors to all Currently does not work for the case where
483     //number of array elements less than number of processors
484     //Will fix it later!
485     if(nSrcIndices == 0 || nDestIndices == 0) {
486         npes = CkNumPes();        
487         pelist = new int[npes];
488         for(count = 0; count < CkNumPes(); count ++) 
489             pelist[count] = count;                         
490     }
491     else {
492         getDestinationPeList(pelist, npes);
493         
494         //Destination has not been set
495         //Strategy does not care about destination
496         //Is an error case
497         if(npes == 0)
498             pelist = new int[CkNumPes()];
499         
500         CkArray *amgr = CkArrayID::CkLocalBranch(src_aid);
501
502         //Add source processors to the destination processors
503         //already obtained
504         for(int acount = 0; acount < nSrcIndices; acount++) {
505           //int p = ComlibGetLastKnown(src_aid, src_elements[acount]);
506             int p = amgr->lastKnown(src_elements[acount]);
507
508             for(count = 0; count < npes; count ++)
509                 if(pelist[count] == p)
510                     break;
511             if(count == npes)
512                 pelist[npes ++] = p;
513         }                        
514     }
515 }
516 */
517
518 /**  Broadcast the message to all local elements (as listed in dest_elements) */
519 void ComlibArrayInfo::localBroadcast(envelope *env) {
520   int count = localMulticast(&dest_elements, env);
521   if(com_debug){
522     CkPrintf("[%d] ComlibArrayInfo::localBroadcast to %d elements (%d non local)\n",CmiMyPe(),dest_elements.size(),count);
523     printDestElementList();
524   }
525
526 }
527
528
529
530 /**
531   This method multicasts the message to all the indices in vec.  It
532   also takes care to check if the entry method is readonly or not. If
533   readonly (nokeep) the message is not copied.
534
535   It also makes sure that the entry methods are logged in projections
536   and that the array manager is notified about array element
537   migrations.  Hence this function should be used extensively in the
538   communication library strategies
539
540   This method is more general than just ComlibArrayInfo dest_aid since it takes
541   the destination array id directly form the message envelope.
542
543   @return the number of destination objects which were not local (information
544   retrieved from the array/location manager)
545
546   @todo Replace this method with calls to CharmStrategy::deliverToIndices, possibly making it a function that is not part of any class
547
548 */
549 #include "register.h"
550 int ComlibArrayInfo::localMulticast(CkVec<CkArrayIndexMax>*vec,
551                                      envelope *env){
552   int count = 0;
553     //Multicast the messages to all elements in vec
554     int nelements = vec->size();
555     if(nelements == 0) {
556         CmiFree(env);
557         return 0;
558     }
559
560     void *msg = EnvToUsr(env);
561     int ep = env->getsetArrayEp();
562     CkUnpackMessage(&env);
563
564     CkArrayID destination_aid = env->getsetArrayMgr();
565     env->setPacked(0);
566     env->getsetArrayHops()=1;
567     env->setUsed(0);
568
569     CkArrayIndexMax idx;
570
571     //ComlibPrintf("sending to %d elements\n",nelements);
572     for(int i = 0; i < nelements-1; i ++){
573       idx = (*vec)[i];
574       CkAssert(idx.nInts == 1);
575         //if(com_debug) idx.print();
576
577         env->getsetArrayIndex() = idx;
578         //ComlibPrintf("sending to: "); idx.print();
579         
580         CkArray *a=(CkArray *)_localBranch(destination_aid);
581         if(_entryTable[ep]->noKeep)
582             count += a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
583         else {
584             void *newmsg = CkCopyMsg(&msg);
585             count += a->deliver((CkArrayMessage *)newmsg, CkDeliver_queue);
586         }
587
588     }
589
590     idx = (*vec)[nelements-1];
591     //if(com_debug) idx.print();
592     env->getsetArrayIndex() = idx;
593     //ComlibPrintf("sending to: "); idx.print();
594     
595     CkArray *a=(CkArray *)_localBranch(destination_aid);
596     if(_entryTable[ep]->noKeep) {
597         count += a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
598         CmiFree(env);
599     }
600     else
601         count += a->deliver((CkArrayMessage *)msg, CkDeliver_queue);
602
603     return count;
604 }
605
606 /** Delivers a message to an array element, making sure that
607     projections is notified */
608 void ComlibArrayInfo::deliver(envelope *env){
609     ComlibPrintf("In ComlibArrayInfo::deliver()\n");
610                 
611     env->setUsed(0);
612     env->getsetArrayHops()=1;
613     CkUnpackMessage(&env);
614     
615     CkArray *a=(CkArray *)_localBranch(env->getsetArrayMgr());
616     a->deliver((CkArrayMessage *)EnvToUsr(env), CkDeliver_queue);
617 }
618
619
620 /*@}*/