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