Merge branch 'charm' of charmgit:charm into charm
[charm.git] / src / ck-com / ComlibSectionInfo.C
1 /**
2    @addtogroup CharmComlib
3    @{ 
4    @file
5   
6    Implementations of classes defined in ComlibSectionInfo.h
7 */
8
9 #include "ComlibManager.h"
10 #include "ComlibSectionInfo.h"
11 #ifdef __MINGW_H 
12 #include <malloc.h> 
13 #endif
14
15
16 #define USE_CONTROL_POINTS 0
17
18 #if USE_CONTROL_POINTS
19 #include "controlPoints.h"
20 #endif
21
22 #if CMK_HAS_ALLOCA_H
23 #include <alloca.h>
24 #endif
25
26
27
28 /**
29    Create a new multicast message based upon the section info stored inside cmsg.
30 */
31 ComlibMulticastMsg * ComlibSectionInfo::getNewMulticastMessage(CharmMessageHolder *cmsg, int needSort, int instanceID){
32     
33   //  cmsg->checkme();
34
35     if(cmsg->sec_id == NULL || cmsg->sec_id->_nElems == 0)
36         return NULL;
37
38     void *m = cmsg->getCharmMessage();
39     envelope *env = UsrToEnv(m);
40         
41     // Crate a unique identifier for section id in cmsg->sec_id
42     initSectionID(cmsg->sec_id);   
43
44     CkPackMessage(&env);
45
46     const CkArrayID destArrayID(env->getsetArrayMgr());
47     int nRemotePes=-1, nRemoteIndices=-1;
48     ComlibMulticastIndexCount *indicesCount;
49     int *belongingList;
50
51
52     //  Determine the last known locations of all the destination objects.
53     getPeCount(cmsg->sec_id->_nElems, cmsg->sec_id->_elems, destArrayID, nRemotePes, nRemoteIndices, indicesCount, belongingList);
54
55     //     if (nRemotePes == 0) return NULL;
56
57 #if 0
58     CkPrintf("nRemotePes=%d\n", nRemotePes);
59     CkPrintf("nRemoteIndices=%d\n",nRemoteIndices);
60     CkPrintf("env->getTotalsize()=%d\n", env->getTotalsize());
61     CkPrintf("cmsg->sec_id->_nElems=%d\n", cmsg->sec_id->_nElems);
62  #endif
63
64     int sizes[3];
65     sizes[0] = nRemotePes;
66     sizes[1] = nRemoteIndices; // only those remote ///cmsg->sec_id->_nElems;
67     sizes[2] = env->getTotalsize();
68     
69     ComlibPrintf("Creating new comlib multicast message %d, %d %d\n", sizes[0], sizes[1], sizes[2]);
70     
71     ComlibMulticastMsg *msg = new(sizes, 0) ComlibMulticastMsg;
72     msg->nPes = nRemotePes;
73     msg->_cookie.info.sInfo.cInfo.instId = instanceID;
74     msg->_cookie.info.sInfo.cInfo.id = MaxSectionID - 1;
75     msg->_cookie.info.sInfo.cInfo.status = COMLIB_MULTICAST_NEW_SECTION;
76     msg->_cookie.get_type() = COMLIB_MULTICAST_MESSAGE;
77     msg->_cookie.get_pe() = CkMyPe();
78
79     // fill in the three pointers of the ComlibMulticastMsg
80     memcpy(msg->indicesCount, indicesCount, sizes[0] * sizeof(ComlibMulticastIndexCount));
81     //memcpy(msg->indices, cmsg->sec_id->_elems, sizes[1] * sizeof(CkArrayIndex));
82
83     CkArrayIndex **indicesPe = (CkArrayIndex**)alloca(nRemotePes * sizeof(CkArrayIndex*));
84
85     if (needSort) {
86         // if we are sorting the array, then we need to fix the problem that belongingList
87         // refers to the original ordering! This is done by mapping indicesPe in a way coherent
88         // with the original ordering.
89         int previous, i, j;
90         qsort(msg->indicesCount, sizes[0], sizeof(ComlibMulticastIndexCount), indexCountCompare);
91
92         for (j=0; j<nRemotePes; ++j) if (indicesCount[j].pe == msg->indicesCount[0].pe) break;
93         indicesPe[j] = msg->indices;
94         previous = j;
95         for (i=1; i<nRemotePes; ++i) {
96                 for (j=0; j<nRemotePes; ++j) if (indicesCount[j].pe == msg->indicesCount[i].pe) break;
97                 indicesPe[j] = indicesPe[previous] + indicesCount[previous].count;
98                 previous = j;
99         }
100     } else {
101         indicesPe[0] = msg->indices;
102         for (int i=1; i<nRemotePes; ++i) indicesPe[i] = indicesPe[i-1] + indicesCount[i-1].count;
103     }
104
105     for (int i=0; i<cmsg->sec_id->_nElems; ++i) {
106         if (belongingList[i] >= 0) {
107                 // If the object is located on a remote PE (-1 is local)
108                 *indicesPe[belongingList[i]] = cmsg->sec_id->_elems[i];
109                 indicesPe[belongingList[i]]++;
110         }
111     }
112     memcpy(msg->usrMsg, env, sizes[2] * sizeof(char));
113     envelope *newenv = UsrToEnv(msg);
114     delete [] indicesCount;
115     delete [] belongingList;
116
117     newenv->getsetArrayMgr() = env->getsetArrayMgr();
118     newenv->getsetArraySrcPe() = env->getsetArraySrcPe();
119     newenv->getsetArrayEp() = env->getsetArrayEp();
120     newenv->getsetArrayHops() = env->getsetArrayHops();
121     newenv->getsetArrayIndex() = env->getsetArrayIndex();
122
123     // for trace projections
124     newenv->setEvent(env->getEvent());
125     newenv->setSrcPe(env->getSrcPe());
126     
127     return (ComlibMulticastMsg *)EnvToUsr(newenv);
128 }
129
130 void ComlibSectionInfo::getPeList(envelope *cb_env, int npes, int *&pelist)
131 {
132     ComlibMulticastMsg *ccmsg = (ComlibMulticastMsg *)EnvToUsr(cb_env);
133     int i;
134     
135     CkAssert(npes==ccmsg->nPes);
136     for (i=0; i<ccmsg->nPes; ++i) {
137       pelist[i]=ccmsg->indicesCount[i].pe;
138     }
139
140 }
141
142
143 void ComlibSectionInfo::unpack(envelope *cb_env,
144                                int &nLocalElems,
145                                CkArrayIndex *&dest_indices, 
146                                envelope *&env) {
147         
148     ComlibMulticastMsg *ccmsg = (ComlibMulticastMsg *)EnvToUsr(cb_env);
149     int i;
150
151     dest_indices = ccmsg->indices;
152     for (i=0; i<ccmsg->nPes; ++i) {
153       if (ccmsg->indicesCount[i].pe == CkMyPe()) break;
154       dest_indices += ccmsg->indicesCount[i].count;
155     }
156
157     if(i >= ccmsg->nPes)
158       {  //cheap hack for rect bcast
159         nLocalElems=0;
160         dest_indices=NULL;
161       }
162     else
163       {
164     nLocalElems = ccmsg->indicesCount[i].count;
165
166     /*
167     ComlibPrintf("Unpacking: %d local elements:",nLocalElems);
168     for (int j=0; j<nLocalElems; ++j) ComlibPrintf(" %d",((int*)&dest_indices[j])[1]);
169     ComlibPrintf("\n");
170     */
171     /*
172     for(int count = 0; count < ccmsg->nIndices; count++){
173         CkArrayIndex idx = ccmsg->indices[count];
174         
175         //This will work because. lastknown always knows if I have the
176         //element of not
177         int dest_proc = ComlibGetLastKnown(destArrayID, idx);
178         //CkArrayID::CkLocalBranch(destArrayID)->lastKnown(idx);
179         
180         //        if(dest_proc == CkMyPe())
181         dest_indices.insertAtEnd(idx);                        
182     }
183     */
184       }
185     envelope *usrenv = (envelope *) ccmsg->usrMsg;
186     env = (envelope *)CmiAlloc(usrenv->getTotalsize());
187     memcpy(env, usrenv, usrenv->getTotalsize());
188     env->setEvent(cb_env->getEvent());
189 }
190
191
192 void ComlibSectionInfo::processOldSectionMessage(CharmMessageHolder *cmsg) {
193   //  cmsg->checkme();
194
195     ComlibPrintf("Process Old Section Message \n");
196
197     int cur_sec_id = cmsg->sec_id->getSectionID();
198
199     //Old section id, send the id with the message
200     CkMcastBaseMsg *cbmsg = (CkMcastBaseMsg *)cmsg->getCharmMessage();
201     cbmsg->_cookie.get_pe() = CkMyPe();
202     cbmsg->_cookie.info.sInfo.cInfo.id = cur_sec_id;
203     cbmsg->_cookie.info.sInfo.cInfo.status = COMLIB_MULTICAST_OLD_SECTION;
204 }
205
206 CkMcastBaseMsg *ComlibSectionInfo::getNewDeliveryErrorMsg(CkMcastBaseMsg *base) {
207   CkMcastBaseMsg *dest= (CkMcastBaseMsg*)CkAllocMsg(0, sizeof(CkMcastBaseMsg), 0);
208   memcpy(dest, base, sizeof(CkMcastBaseMsg));
209   dest->_cookie.info.sInfo.cInfo.status = COMLIB_MULTICAST_SECTION_ERROR;
210   return dest;
211 }
212
213 void ComlibSectionInfo::getPeList(int _nElems, 
214                                   CkArrayIndex *_elems,
215                                   CkArrayID &destArrayID,
216                                   int &npes, int *&pelist){
217
218     int length = CkNumPes();
219     if(length > _nElems)    //There will not be more processors than
220                             //number of elements. This is wastage of
221                             //memory as there may be fewer
222                             //processors. Fix later.
223         length = _nElems;
224     
225     pelist = new int[length];
226     npes = 0;
227     
228     int count = 0, acount = 0;
229     
230     CkArray *a = (CkArray *)_localBranch(destArrayID);
231     for(acount = 0; acount < _nElems; acount++){
232         
233       //int p = ComlibGetLastKnown(destArrayID, _elems[acount]);
234         int p = a->lastKnown(_elems[acount]);
235         
236         if(p == -1) CkAbort("Invalid Section\n");        
237         for(count = 0; count < npes; count ++)
238             if(pelist[count] == p)
239                 break;
240         
241         if(count == npes) {
242           pelist[npes ++] = p;
243         }
244     }   
245     
246     if(npes == 0) {
247       delete [] pelist;
248       pelist = NULL;
249     }
250 }
251
252
253
254 inline int getPErepresentingNodeContainingPE(int pe){
255
256 #if 1
257     return pe;
258
259 #else
260
261 #if USE_CONTROL_POINTS
262   std::vector<int> v;
263   v.push_back(1);
264   if(CkNumPes() >= 2)
265     v.push_back(2);
266   if(CkNumPes() >= 4)
267     v.push_back(4);
268   if(CkNumPes() >= 8)
269     v.push_back(8);
270   int pes_per_node = controlPoint("Number of PEs per Node", v);
271 #else
272   int pes_per_node = 1;
273 #endif
274
275
276     if(getenv("PE_PER_NODES") != NULL)
277         pes_per_node = CkNumPes()/atoi(getenv("PE_PER_NODES"));
278             
279     if( pes_per_node > 1 && pes_per_node <= CkNumPes() ){
280         ComlibPrintf("NODE AWARE Sending a message to a representative of the node instead of its real owner\n");
281         int newpe = pe - (pe % pes_per_node);
282         return newpe;
283     } else {
284         return pe;
285     }
286 #endif    
287 }
288
289 /** 
290     Determine the last known locations of all the destination objects.
291
292     Create two resulting arrays:
293         1) counts -- contains pairs of (pe,count) that describe how many objects were found for each of the pe's
294         2) belongs -- belongs[i] points to the owning pe's entry in the "counts" array.
295         
296 */
297 void ComlibSectionInfo::getPeCount(int nindices, CkArrayIndex *idxlist, 
298                       const CkArrayID &destArrayID, int &npes, int &nidx,
299                       ComlibMulticastIndexCount *&counts, int *&belongs) {
300
301   int i;
302     
303   int length = CkNumPes();
304
305   if(length > nindices) length = nindices;
306     
307   counts = new ComlibMulticastIndexCount[length];
308   belongs = new int[nindices];
309   npes = 0;
310   nidx = 0;
311
312   CkArray *a = (CkArray *)_localBranch(destArrayID);
313   for(i=0; i<nindices; ++i){
314     int p = a->lastKnown(idxlist[i]);
315
316 #define USE_NODE_AWARE 0
317 #if USE_NODE_AWARE
318     //#warning "USING NODE AWARE SECTION INFOs"
319     ComlibPrintf("NODE AWARE old p=%d\n", p);
320   
321     // p = getPErepresentingNodeContainingPE(p);
322     
323     ComlibPrintf("NODE AWARE new p=%d\n", p);
324 #endif
325     
326     if(p == -1) CkAbort("Invalid Section\n");        
327
328     if(p == CkMyPe()) {
329       belongs[i] = -1;
330       continue;
331     }
332
333     //Collect processors
334     int count = 0;
335     for(count = 0; count < npes; count ++)
336       if(counts[count].pe == p)
337         break;
338     
339     if(count == npes) {
340       counts[npes].pe = p;
341       counts[npes].count = 0;
342       ++npes;
343     }
344
345     ++nidx;
346     counts[count].count++;
347     belongs[i] = count;
348   }
349   //ComlibPrintf("section has %d procs\n",npes);
350
351 //   if(npes == 0) {
352 //     delete [] counts;
353 //     delete [] belongs;
354 //     counts = NULL;
355 //     belongs = NULL;
356 //   }
357 }
358
359
360 void ComlibSectionInfo::getRemotePelist(int nindices, 
361                                         CkArrayIndex *idxlist,
362                                         CkArrayID &destArrayID,
363                                         int &npes, int *&pelist) {
364
365         ComlibPrintf("ComlibSectionInfo::getRemotePelist()\n");
366         
367     int count = 0, acount = 0;
368     
369     int length = CkNumPes();
370
371     // HACK FOR DEBUGGING
372     /*pelist = new int[length-1];
373     npes = length-1;
374     for (acount=0; acount<length; acount++) {
375       if (acount == CkMyPe()) continue;
376       pelist[count]=acount;
377       count++;
378     }
379     return;*/
380     // END HACK
381
382     if(length > nindices)
383         length = nindices;
384     
385     pelist = new int[length+1];
386     npes = 0;
387
388     CkArray *a = (CkArray *)_localBranch(destArrayID);
389     for(acount = 0; acount < nindices; acount++){
390         
391       //int p = ComlibGetLastKnown(destArrayID, idxlist[acount]);
392       int p = a->lastKnown(idxlist[acount]);
393       if(p == CkMyPe())
394             continue;
395         
396         if(p == -1) CkAbort("Invalid Section\n");        
397         
398         //Collect remote processors
399         for(count = 0; count < npes; count ++)
400             if(pelist[count] == p)
401                 break;
402         
403         if(count == npes) {
404             pelist[npes ++] = p;
405         }
406     }
407     
408     if(npes == 0) {
409         delete [] pelist;
410         pelist = NULL;
411     }
412 }
413
414
415 void ComlibSectionInfo::getLocalIndices(int nindices,
416                                         CkArrayIndex *idxlist,
417                                         CkArrayID &destArrayID,
418                                         CkVec<CkArrayIndex> &idx_vec){    
419         ComlibPrintf("ComlibSectionInfo::getLocalIndices()\n");
420         
421         int acount = 0;
422     idx_vec.resize(0);
423     
424     CkArray *a = (CkArray *)_localBranch(destArrayID);
425     for(acount = 0; acount < nindices; acount++){
426         //int p = ComlibGetLastKnown(destArrayID, idxlist[acount]);
427         int p = a->lastKnown(idxlist[acount]);
428         if(p == CkMyPe()) 
429             idx_vec.insertAtEnd(idxlist[acount]);
430     }
431 }
432
433
434
435 void ComlibSectionInfo::getNodeLocalIndices(int nindices,
436                                         CkArrayIndex *idxlist,
437                                         CkArrayID &destArrayID,
438                                         CkVec<CkArrayIndex> &idx_vec){    
439     int acount = 0;
440     idx_vec.resize(0);
441     
442     CkArray *a = (CkArray *)_localBranch(destArrayID);
443     for(acount = 0; acount < nindices; acount++){
444         //int p = ComlibGetLastKnown(destArrayID, idxlist[acount]);
445         int p = a->lastKnown(idxlist[acount]);
446         if(p == CkMyPe()) 
447             idx_vec.insertAtEnd(idxlist[acount]);
448     }
449 }
450
451