Fixing projections message tracing for [nokeep] multicast messages. Projections messa...
[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 void ComlibGroupInfo::getCombinedPeList(int *&pelist, int &npes) {
234     int count = 0;        
235     pelist = 0;
236     npes = 0;
237
238     pelist = new int[CkNumPes()];
239     if(nsrcpes == 0 || ndestpes == 0) {
240         npes = CkNumPes();        
241         for(count = 0; count < CkNumPes(); count ++) 
242             pelist[count] = count;                         
243     }
244     else {        
245         npes = ndestpes;
246         memcpy(pelist, destpelist, npes * sizeof(int));
247         
248         //Add source processors to the destination processors
249         //already obtained
250         for(int count = 0; count < nsrcpes; count++) {
251             int p = srcpelist[count];
252
253             for(count = 0; count < npes; count ++)
254                 if(pelist[count] == p)
255                     break;
256
257             if(count == npes)
258                 pelist[npes ++] = p;
259         }                        
260     }
261 }
262 */
263
264 ComlibArrayInfo::ComlibArrayInfo() {
265         
266     src_aid.setZero();
267     //nSrcIndices = -1;
268     //src_elements = NULL;
269     isAllSrc = 0;
270     totalSrc = 0;
271     isSrcArray = 0;
272
273     dest_aid.setZero();
274     //nDestIndices = -1;
275     //dest_elements = NULL;
276     isAllDest = 0;
277     totalDest = 0;
278     isDestArray = 0;
279 };
280
281 /*
282 ComlibArrayInfo::~ComlibArrayInfo() {
283     //CkPrintf("in comlibarrayinfo destructor\n");
284
285     if(nSrcIndices > 0)
286         delete [] src_elements;
287
288     if(nDestIndices > 0)
289         delete [] dest_elements;
290 }
291 */
292
293 /// Set the  source array used for this strategy. 
294 /// The list of array indices should be the whole portion of the array involved in the strategy.
295 /// The non-local array elements will be cleaned up inside purge() at migration of the strategy
296 void ComlibArrayInfo::setSourceArray(CkArrayID aid, 
297                                          CkArrayIndexMax *e, int nind){
298     src_aid = aid;
299     isSrcArray = 1;
300     /*
301     nSrcIndices = nind;
302     if(nind > 0) {
303         src_elements = new CkArrayIndexMax[nind];
304         memcpy(src_elements, e, sizeof(CkArrayIndexMax) * nind);
305     }
306     */
307     src_elements.removeAll();
308     
309     for (int i=0; i<nind; ++i) src_elements.push_back(e[i]);
310     
311     if (src_elements.size() == 0) 
312         isAllSrc = 1;
313     else 
314         isAllSrc = 0;
315     
316     totalSrc = src_elements.size();
317     
318 }
319
320
321 void ComlibArrayInfo::getSourceArray(CkArrayID &aid, 
322                                          CkArrayIndexMax *&e, int &nind){
323     aid = src_aid;
324     nind = src_elements.length();//nSrcIndices;
325     e = src_elements.getVec();//src_elements;
326 }
327
328
329 void ComlibArrayInfo::setDestinationArray(CkArrayID aid, 
330                                           CkArrayIndexMax *e, int nind){
331     dest_aid = aid;
332     isDestArray = 1;
333     /*
334     nDestIndices = nind;
335     if(nind > 0) {
336         dest_elements = new CkArrayIndexMax[nind];
337         memcpy(dest_elements, e, sizeof(CkArrayIndexMax) * nind);
338     }
339     */
340     dest_elements.removeAll();
341     for (int i=0; i<nind; ++i) dest_elements.push_back(e[i]);
342
343     if (dest_elements.size() == 0) 
344         isAllDest = 1;
345     else 
346         isAllDest = 0;
347     
348     totalDest = dest_elements.size();
349     
350 }
351
352
353 void ComlibArrayInfo::getDestinationArray(CkArrayID &aid, 
354                                           CkArrayIndexMax *&e, int &nind){
355     aid = dest_aid;
356     nind = dest_elements.length();
357     e = dest_elements.getVec();
358 }
359
360 /// @TODO fix the pup!
361 //Each strategy must define his own Pup interface.
362 void ComlibArrayInfo::pup(PUP::er &p){ 
363     p | src_aid;
364     //p | nSrcIndices;
365     p | isSrcArray;
366     p | isAllSrc;
367     p | totalSrc;
368     p | src_elements;
369     
370     p | dest_aid;
371     //p | nDestIndices;
372     p | isDestArray;
373     p | isAllDest;
374     p | totalDest;
375     p | dest_elements;
376
377     if (p.isPacking() || p.isUnpacking()) {
378       // calling purge both during packing (at the end) and during unpacking
379       // allows this code to be executed both on processor 0 (where the object
380       // is created) and on every other processor where it arrives through PUP.
381       purge();
382     }
383
384     /*    
385     if(p.isUnpacking() && nSrcIndices > 0) 
386         src_elements = new CkArrayIndexMax[nSrcIndices];
387     
388     if(p.isUnpacking() && nDestIndices > 0) 
389         dest_elements = new CkArrayIndexMax[nDestIndices];        
390     
391     if(nSrcIndices > 0)
392         p((char *)src_elements, nSrcIndices * sizeof(CkArrayIndexMax));    
393     else
394         src_elements = NULL;
395
396     if(nDestIndices > 0)
397         p((char *)dest_elements, nDestIndices * sizeof(CkArrayIndexMax));    
398     else
399         dest_elements = NULL;
400
401     localDestIndexVec.resize(0);
402     */
403     
404 }
405
406 void ComlibArrayInfo::newElement(CkArrayID &id, const CkArrayIndex &idx) {
407   ComlibPrintf("ComlibArrayInfo::newElement\n");
408   if (isAllSrc && id==src_aid) src_elements.push_back(idx);
409   if (isAllDest && id==dest_aid) dest_elements.push_back(idx);
410 }
411
412 void ComlibArrayInfo::purge() {
413         int i;
414         CkArray *a;
415 //      ComlibPrintf("[%d] ComlibArrayInfo::purge srcArray=%d (%d), destArray=%d (%d)\n",CkMyPe(),isSrcArray,isAllSrc,isDestArray,isAllDest);
416         if (isSrcArray) {
417                 a = (CkArray *)_localBranch(src_aid);
418                 if (isAllSrc) {
419                         // gather the information of all the elements that are currenly present here
420                         ComlibElementIterator iter(&src_elements);
421                         a->getLocMgr()->iterate(iter);
422
423                         // register to ComlibArrayListener for this array id
424 //                      ComlibManagerRegisterArrayListener(src_aid, this);
425                 } else {
426                         // delete all the elements of which we are not homePe
427                         for (i=src_elements.size()-1; i>=0; --i) {
428                                 if (a->homePe(src_elements[i]) != CkMyPe()) { 
429                                         
430 //                                      ComlibPrintf("[%d] removing home=%d src element %d  i=%d\n", CkMyPe(),a->homePe(src_elements[i]), src_elements[i].data()[0], i);
431                                         src_elements.remove(i); 
432                                 }
433                         }
434                 }
435         }
436         if (isDestArray) {
437                 a = (CkArray *)_localBranch(dest_aid);
438                 if (isAllDest) {
439                         // gather the information of all the elements that are currenly present here
440                         ComlibElementIterator iter(&dest_elements);
441                         a->getLocMgr()->iterate(iter);
442
443                         // register to ComlibArrayListener for this array id
444 //                      ComlibManagerRegisterArrayListener(dest_aid, this);
445                 } else {
446                         // delete all the elements of which we are not homePe
447                         for (i=dest_elements.size()-1; i>=0; --i) {
448                                 if (a->homePe(dest_elements[i]) != CkMyPe()) {
449 //                                      ComlibPrintf("[%d] removing home=%d dest element %d  i=%d\n", CkMyPe(), a->homePe(dest_elements[i]), dest_elements[i].data()[0], i);
450                                         dest_elements.remove(i); 
451                                 }
452                         }
453                 }
454         }
455 }
456
457 int *ComlibArrayInfo::getCombinedCountList() {
458   int *result = new int[CkNumPes()];
459   int i;
460   for (i=0; i<CkNumPes(); ++i) result[i] = 0;
461   CkArray *a = (CkArray *)_localBranch(src_aid);
462   if (src_elements.size() != 0) {
463     for (i=0; i<src_elements.size(); ++i) result[a->homePe(src_elements[i])] |= 1;
464   } else {
465     for (i=0; i<CkNumPes(); ++i) result[i] |= 1;
466   }
467   a = (CkArray *)_localBranch(dest_aid);
468   if (dest_elements.size() != 0) {
469     for (i=0; i<dest_elements.size(); ++i) result[a->homePe(dest_elements[i])] |= 2;
470   } else {
471     for (i=0; i<CkNumPes(); ++i) result[i] |= 2;
472   }
473   return result;
474 }
475
476 /*
477 //Get the list of destination processors
478 void ComlibArrayInfo::getDestinationPeList(int *&destpelist, int &ndestpes) {
479     
480     int count = 0, acount =0;
481     
482     //Destination has not been set
483     if(nDestIndices < 0) {
484         destpelist = 0;
485         ndestpes = 0;
486         return;
487     }
488
489     //Create an array of size CkNumPes()
490     //Inefficient in space
491     ndestpes = CkNumPes();
492     destpelist = new int[ndestpes];
493
494     memset(destpelist, 0, ndestpes * sizeof(int));    
495
496     if(nDestIndices == 0){
497         for(count =0; count < CkNumPes(); count ++) 
498             destpelist[count] = count;             
499         return;
500     }
501
502     ndestpes = 0;
503     CkArray *amgr = CkArrayID::CkLocalBranch(dest_aid);
504
505     //Find the last known processors of the array elements
506     for(acount = 0; acount < nDestIndices; acount++) {
507
508       //int p = ComlibGetLastKnown(dest_aid, dest_elements[acount]); 
509         int p = amgr->lastKnown(dest_elements[acount]);
510         
511         for(count = 0; count < ndestpes; count ++)
512             if(destpelist[count] == p)
513                 break;
514         
515         if(count == ndestpes) {
516             destpelist[ndestpes ++] = p; 
517         }       
518     }                            
519 }
520
521 void ComlibArrayInfo::getSourcePeList(int *&srcpelist, int &nsrcpes) {
522     
523     int count = 0, acount =0;
524
525     if(nSrcIndices < 0) {
526         srcpelist = 0;
527         nsrcpes = 0;
528         return;
529     }
530
531     nsrcpes = CkNumPes();
532     srcpelist = new int[nsrcpes];
533
534     memset(srcpelist, 0, nsrcpes * sizeof(int));    
535
536     if(nSrcIndices == 0){
537         for(count =0; count < CkNumPes(); count ++) 
538             srcpelist[count] = count;             
539         return;
540     }
541
542     nsrcpes = 0;
543     CkArray *amgr = CkArrayID::CkLocalBranch(src_aid);
544
545     for(acount = 0; acount < nSrcIndices; acount++) {
546         
547       //int p = ComlibGetLastKnown(src_aid, src_elements[acount]); 
548         int p = amgr->lastKnown(src_elements[acount]);
549         
550         for(count = 0; count < nsrcpes; count ++)
551             if(srcpelist[count] == p)
552                 break;
553         
554         if(count == nsrcpes) {
555             srcpelist[nsrcpes ++] = p; 
556         }       
557     }                            
558 }
559
560 void ComlibArrayInfo::getCombinedPeList(int *&pelist, int &npes) {
561
562     int count = 0;        
563     pelist = 0;
564     npes = 0;
565     
566     //Both arrays empty;
567     //Sanity check, this should really not happen
568     if(nSrcIndices < 0 && nDestIndices < 0) {
569         CkAbort("Arrays have not been set\n");
570         return;
571     }
572     
573     //One of them is the entire array Hence set the number of
574     //processors to all Currently does not work for the case where
575     //number of array elements less than number of processors
576     //Will fix it later!
577     if(nSrcIndices == 0 || nDestIndices == 0) {
578         npes = CkNumPes();        
579         pelist = new int[npes];
580         for(count = 0; count < CkNumPes(); count ++) 
581             pelist[count] = count;                         
582     }
583     else {
584         getDestinationPeList(pelist, npes);
585         
586         //Destination has not been set
587         //Strategy does not care about destination
588         //Is an error case
589         if(npes == 0)
590             pelist = new int[CkNumPes()];
591         
592         CkArray *amgr = CkArrayID::CkLocalBranch(src_aid);
593
594         //Add source processors to the destination processors
595         //already obtained
596         for(int acount = 0; acount < nSrcIndices; acount++) {
597           //int p = ComlibGetLastKnown(src_aid, src_elements[acount]);
598             int p = amgr->lastKnown(src_elements[acount]);
599
600             for(count = 0; count < npes; count ++)
601                 if(pelist[count] == p)
602                     break;
603             if(count == npes)
604                 pelist[npes ++] = p;
605         }                        
606     }
607 }
608 */
609
610 /// Broadcast the message to all local elements
611 void ComlibArrayInfo::localBroadcast(envelope *env) {
612   int count = localMulticast(&dest_elements, env);
613   ComlibPrintf("[%d] ComlibArrayInfo::localBroadcast to %d elements (%d non local)\n",CmiMyPe(),dest_elements.size(),count);
614
615 //  char buf[100000];
616 //  buf[0] = '\0';
617 //  for(int i=0;i<dest_elements.size();i++){
618 //        sprintf(buf+strlen(buf), " %d", dest_elements[i].data()[0]);
619 //  }
620 //  ComlibPrintf("dest_elements = %s\n", buf);
621
622 }
623
624 /**
625   This method multicasts the message to all the indices in vec.  It
626   also takes care to check if the entry method is readonly or not. If
627   readonly (nokeep) the message is not copied.
628
629   It also makes sure that the entry methods are logged in projections
630   and that the array manager is notified about array element
631   migrations.  Hence this function should be used extensively in the
632   communication library strategies
633
634   This method is more general than just ComlibArrayInfo dest_aid since it takes
635   the destination array id directly form the message envelope.
636
637   @return the number of destination objects which were not local (information
638   retrieved from the array/location manager)
639
640   @todo Replace this method with calls to CharmStrategy::deliverToIndices, possibly making it a function that is not part of any class
641
642 */
643
644 #include "register.h"
645 int ComlibArrayInfo::localMulticast(CkVec<CkArrayIndexMax>*vec,
646                                      envelope *env){
647   int count = 0;
648     //Multicast the messages to all elements in vec
649     int nelements = vec->size();
650     if(nelements == 0) {
651         CmiFree(env);
652         return 0;
653     }
654
655     void *msg = EnvToUsr(env);
656     int ep = env->getsetArrayEp();
657     CkUnpackMessage(&env);
658
659     CkArrayID destination_aid = env->getsetArrayMgr();
660     env->setPacked(0);
661     env->getsetArrayHops()=1;
662     env->setUsed(0);
663
664     CkArrayIndexMax idx;
665
666     //ComlibPrintf("sending to %d elements\n",nelements);
667     for(int i = 0; i < nelements-1; i ++){
668         idx = (*vec)[i];
669         //if(com_debug) idx.print();
670
671         env->getsetArrayIndex() = idx;
672         //ComlibPrintf("sending to: "); idx.print();
673         
674         CkArray *a=(CkArray *)_localBranch(destination_aid);
675         if(_entryTable[ep]->noKeep)
676             count += a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
677         else {
678             void *newmsg = CkCopyMsg(&msg);
679             count += a->deliver((CkArrayMessage *)newmsg, CkDeliver_queue);
680         }
681
682     }
683
684     idx = (*vec)[nelements-1];
685     //if(com_debug) idx.print();
686     env->getsetArrayIndex() = idx;
687     //ComlibPrintf("sending to: "); idx.print();
688     
689     CkArray *a=(CkArray *)_localBranch(destination_aid);
690     if(_entryTable[ep]->noKeep) {
691         count += a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
692         CmiFree(env);
693     }
694     else
695         count += a->deliver((CkArrayMessage *)msg, CkDeliver_queue);
696
697     return count;
698 }
699
700 /** Delivers a message to an array element, making sure that
701     projections is notified */
702 void ComlibArrayInfo::deliver(envelope *env){
703     ComlibPrintf("In ComlibArrayInfo::deliver()\n");
704                 
705     env->setUsed(0);
706     env->getsetArrayHops()=1;
707     CkUnpackMessage(&env);
708     
709     CkArray *a=(CkArray *)_localBranch(env->getsetArrayMgr());
710     a->deliver((CkArrayMessage *)EnvToUsr(env), CkDeliver_queue);
711 }
712
713
714 /*@}*/