Fixing some bugs in the new node aware multicast strategy.
[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.sInfo.cInfo.instId = instanceID;
74     msg->_cookie.sInfo.cInfo.id = MaxSectionID - 1;
75     msg->_cookie.sInfo.cInfo.status = COMLIB_MULTICAST_NEW_SECTION;
76     msg->_cookie.type = COMLIB_MULTICAST_MESSAGE;
77     msg->_cookie.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(CkArrayIndexMax));
82
83     CkArrayIndexMax **indicesPe = (CkArrayIndexMax**)alloca(nRemotePes * sizeof(CkArrayIndexMax*));
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                                CkArrayIndexMax *&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         CkArrayIndexMax 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, ccmsg->usrMsg, usrenv->getTotalsize());
188 }
189
190
191 void ComlibSectionInfo::processOldSectionMessage(CharmMessageHolder *cmsg) {
192   cmsg->checkme();
193
194     ComlibPrintf("Process Old Section Message \n");
195
196     int cur_sec_id = cmsg->sec_id->getSectionID();
197
198     //Old section id, send the id with the message
199     CkMcastBaseMsg *cbmsg = (CkMcastBaseMsg *)cmsg->getCharmMessage();
200     cbmsg->_cookie.sInfo.cInfo.id = cur_sec_id;
201     cbmsg->_cookie.sInfo.cInfo.status = COMLIB_MULTICAST_OLD_SECTION;
202 }
203
204 CkMcastBaseMsg *ComlibSectionInfo::getNewDeliveryErrorMsg(CkMcastBaseMsg *base) {
205   CkMcastBaseMsg *dest= (CkMcastBaseMsg*)CkAllocMsg(0, sizeof(CkMcastBaseMsg), 0);
206   memcpy(dest, base, sizeof(CkMcastBaseMsg));
207   dest->_cookie.sInfo.cInfo.status = COMLIB_MULTICAST_SECTION_ERROR;
208   return dest;
209 }
210
211 void ComlibSectionInfo::getPeList(int _nElems, 
212                                   CkArrayIndexMax *_elems,
213                                   CkArrayID &destArrayID,
214                                   int &npes, int *&pelist){
215
216     int length = CkNumPes();
217     if(length > _nElems)    //There will not be more processors than
218                             //number of elements. This is wastage of
219                             //memory as there may be fewer
220                             //processors. Fix later.
221         length = _nElems;
222     
223     pelist = new int[length];
224     npes = 0;
225     
226     int count = 0, acount = 0;
227     
228     CkArray *a = (CkArray *)_localBranch(destArrayID);
229     for(acount = 0; acount < _nElems; acount++){
230         
231       //int p = ComlibGetLastKnown(destArrayID, _elems[acount]);
232         int p = a->lastKnown(_elems[acount]);
233         
234         if(p == -1) CkAbort("Invalid Section\n");        
235         for(count = 0; count < npes; count ++)
236             if(pelist[count] == p)
237                 break;
238         
239         if(count == npes) {
240           pelist[npes ++] = p;
241         }
242     }   
243     
244     if(npes == 0) {
245       delete [] pelist;
246       pelist = NULL;
247     }
248 }
249
250
251
252 inline int getPErepresentingNodeContainingPE(int pe){
253
254 #if 1
255     return pe;
256
257 #else
258
259 #if USE_CONTROL_POINTS
260   std::vector<int> v;
261   v.push_back(1);
262   if(CkNumPes() >= 2)
263     v.push_back(2);
264   if(CkNumPes() >= 4)
265     v.push_back(4);
266   if(CkNumPes() >= 8)
267     v.push_back(8);
268   int pes_per_node = controlPoint("Number of PEs per Node", v);
269 #else
270   int pes_per_node = 1;
271 #endif
272
273
274     if(getenv("PE_PER_NODES") != NULL)
275         pes_per_node = CkNumPes()/atoi(getenv("PE_PER_NODES"));
276             
277     if( pes_per_node > 1 && pes_per_node <= CkNumPes() ){
278         ComlibPrintf("NODE AWARE Sending a message to a representative of the node instead of its real owner\n");
279         int newpe = pe - (pe % pes_per_node);
280         return newpe;
281     } else {
282         return pe;
283     }
284 #endif    
285 }
286
287 /** 
288     Determine the last known locations of all the destination objects.
289
290     Create two resulting arrays:
291         1) counts -- contains pairs of (pe,count) that describe how many objects were found for each of the pe's
292         2) belongs -- belongs[i] points to the owning pe's entry in the "counts" array.
293         
294 */
295 void ComlibSectionInfo::getPeCount(int nindices, CkArrayIndexMax *idxlist, 
296                       const CkArrayID &destArrayID, int &npes, int &nidx,
297                       ComlibMulticastIndexCount *&counts, int *&belongs) {
298
299   int i;
300     
301   int length = CkNumPes();
302
303   if(length > nindices) length = nindices;
304     
305   counts = new ComlibMulticastIndexCount[length];
306   belongs = new int[nindices];
307   npes = 0;
308   nidx = 0;
309
310   CkArray *a = (CkArray *)_localBranch(destArrayID);
311   for(i=0; i<nindices; ++i){
312     int p = a->lastKnown(idxlist[i]);
313
314 #define USE_NODE_AWARE 0
315 #if USE_NODE_AWARE
316     //#warning "USING NODE AWARE SECTION INFOs"
317     ComlibPrintf("NODE AWARE old p=%d\n", p);
318   
319     // p = getPErepresentingNodeContainingPE(p);
320     
321     ComlibPrintf("NODE AWARE new p=%d\n", p);
322 #endif
323     
324     if(p == -1) CkAbort("Invalid Section\n");        
325
326     if(p == CkMyPe()) {
327       belongs[i] = -1;
328       continue;
329     }
330
331     //Collect processors
332     int count = 0;
333     for(count = 0; count < npes; count ++)
334       if(counts[count].pe == p)
335         break;
336     
337     if(count == npes) {
338       counts[npes].pe = p;
339       counts[npes].count = 0;
340       ++npes;
341     }
342
343     ++nidx;
344     counts[count].count++;
345     belongs[i] = count;
346   }
347   //ComlibPrintf("section has %d procs\n",npes);
348
349 //   if(npes == 0) {
350 //     delete [] counts;
351 //     delete [] belongs;
352 //     counts = NULL;
353 //     belongs = NULL;
354 //   }
355 }
356
357
358 void ComlibSectionInfo::getRemotePelist(int nindices, 
359                                         CkArrayIndexMax *idxlist,
360                                         CkArrayID &destArrayID,
361                                         int &npes, int *&pelist) {
362
363         ComlibPrintf("ComlibSectionInfo::getRemotePelist()\n");
364         
365     int count = 0, acount = 0;
366     
367     int length = CkNumPes();
368
369     // HACK FOR DEBUGGING
370     /*pelist = new int[length-1];
371     npes = length-1;
372     for (acount=0; acount<length; acount++) {
373       if (acount == CkMyPe()) continue;
374       pelist[count]=acount;
375       count++;
376     }
377     return;*/
378     // END HACK
379
380     if(length > nindices)
381         length = nindices;
382     
383     pelist = new int[length+1];
384     npes = 0;
385
386     CkArray *a = (CkArray *)_localBranch(destArrayID);
387     for(acount = 0; acount < nindices; acount++){
388         
389       //int p = ComlibGetLastKnown(destArrayID, idxlist[acount]);
390       int p = a->lastKnown(idxlist[acount]);
391       if(p == CkMyPe())
392             continue;
393         
394         if(p == -1) CkAbort("Invalid Section\n");        
395         
396         //Collect remote processors
397         for(count = 0; count < npes; count ++)
398             if(pelist[count] == p)
399                 break;
400         
401         if(count == npes) {
402             pelist[npes ++] = p;
403         }
404     }
405     
406     if(npes == 0) {
407         delete [] pelist;
408         pelist = NULL;
409     }
410 }
411
412
413 void ComlibSectionInfo::getLocalIndices(int nindices,
414                                         CkArrayIndexMax *idxlist,
415                                         CkArrayID &destArrayID,
416                                         CkVec<CkArrayIndexMax> &idx_vec){    
417         ComlibPrintf("ComlibSectionInfo::getLocalIndices()\n");
418         
419         int count = 0, acount = 0;
420     idx_vec.resize(0);
421     
422     CkArray *a = (CkArray *)_localBranch(destArrayID);
423     for(acount = 0; acount < nindices; acount++){
424         //int p = ComlibGetLastKnown(destArrayID, idxlist[acount]);
425         int p = a->lastKnown(idxlist[acount]);
426         if(p == CkMyPe()) 
427             idx_vec.insertAtEnd(idxlist[acount]);
428     }
429 }
430
431
432
433 void ComlibSectionInfo::getNodeLocalIndices(int nindices,
434                                         CkArrayIndexMax *idxlist,
435                                         CkArrayID &destArrayID,
436                                         CkVec<CkArrayIndexMax> &idx_vec){    
437     int count = 0, acount = 0;
438     idx_vec.resize(0);
439     
440     CkArray *a = (CkArray *)_localBranch(destArrayID);
441     for(acount = 0; acount < nindices; acount++){
442         //int p = ComlibGetLastKnown(destArrayID, idxlist[acount]);
443         int p = a->lastKnown(idxlist[acount]);
444         if(p == CkMyPe()) 
445             idx_vec.insertAtEnd(idxlist[acount]);
446     }
447 }
448
449