cleanup
[charm.git] / src / ck-ldb / LBSimulation.C
1 /* Implementation of the CLBSimResults class
2  */
3 #include "LBSimulation.h"
4
5 /*****************************************************************************
6                 Sequentail Simulation 
7 *****************************************************************************/
8
9 int LBSimulation::dumpStep = -1;             /// first step number to dump
10 int LBSimulation::dumpStepSize = 1;          /// number of steps to dump 
11 char* LBSimulation::dumpFile = (char*)"lbdata.dat"; /// dump file name
12 int LBSimulation::doSimulation = 0;          /// flag if do simulation
13 int LBSimulation::simStep = -1;              /// first step number to simulate
14 int LBSimulation::simStepSize = 1;           /// number of steps to simulate
15 int LBSimulation::simProcs = 0;              /// simulation target procs
16 int LBSimulation::procsChanged = 0;          /// flag if the number of procs has been changed
17
18 int LBSimulation::showDecisionsOnly = 0;     /// flag to write all LB decisions
19 int _lb_version = LB_FORMAT_VERSION;         /// data file version
20
21 /*****************************************************************************
22                 LBInfo: evaluation information for LBStats  
23 *****************************************************************************/
24
25 LBInfo::LBInfo(int count): numPes(count), minObjLoad(0.0), maxObjLoad(0.0)
26 {
27   peLoads = new LBRealType[numPes]; 
28   objLoads = new LBRealType[numPes]; 
29   comLoads = new LBRealType[numPes]; 
30   bgLoads = new LBRealType[numPes]; 
31   clear();
32 }
33
34 LBInfo::~LBInfo()
35 {
36   // only free when it is allocated in the constructor
37   if (peLoads && bgLoads) {
38     delete [] bgLoads;
39     delete [] comLoads;
40     delete [] objLoads;
41     delete [] peLoads;
42   }
43 }
44
45 void LBInfo::clear()
46 {
47   for (int i=0; i<numPes; i++) {
48     peLoads[i] = 0.0;
49     if (objLoads) objLoads[i] = 0.0;
50     if (comLoads) comLoads[i] = 0.0;
51     if (bgLoads)  bgLoads[i] = 0.0;
52   }
53   minObjLoad = 0.0;
54   maxObjLoad = 0.0;
55   msgCount = msgBytes = 0;
56 }
57
58 void LBInfo::getInfo(BaseLB::LDStats* stats, int count, int considerComm)
59 {
60 #if CMK_LBDB_ON
61         int i, pe;
62
63         CmiAssert(peLoads);
64
65         clear();
66
67         double alpha = _lb_args.alpha();
68         double beeta = _lb_args.beeta();
69
70         minObjLoad = 1.0e20;  // I suppose no object load is beyond this
71         maxObjLoad = 0.0;
72
73         msgCount = 0;
74         msgBytes = 0;
75
76         if (considerComm) stats->makeCommHash();
77
78         // get background load
79         if (bgLoads)
80           for(pe = 0; pe < count; pe++)
81            bgLoads[pe] = stats->procs[pe].bg_walltime;
82
83         for(pe = 0; pe < count; pe++)
84           peLoads[pe] = stats->procs[pe].bg_walltime;
85
86         for(int obj = 0; obj < stats->n_objs; obj++)
87         {
88                 int pe = stats->to_proc[obj];
89                 if (pe == -1) continue;     // this object is out
90                 CmiAssert(pe >=0 && pe < count);
91                 double oload = stats->objData[obj].wallTime;
92                 if (oload < minObjLoad) minObjLoad = oload;
93                 if (oload > maxObjLoad) maxObjLoad = oload;
94                 peLoads[pe] += oload;
95                 if (objLoads) objLoads[pe] += oload;
96         }
97
98         // handling of the communication overheads. 
99         if (considerComm) {
100           int* msgSentCount = new int[count]; // # of messages sent by each PE
101           int* msgRecvCount = new int[count]; // # of messages received by each PE
102           int* byteSentCount = new int[count];// # of bytes sent by each PE
103           int* byteRecvCount = new int[count];// # of bytes reeived by each PE
104           for(i = 0; i < count; i++)
105             msgSentCount[i] = msgRecvCount[i] = byteSentCount[i] = byteRecvCount[i] = 0;
106
107           int mcast_count = 0;
108           for (int cidx=0; cidx < stats->n_comm; cidx++) {
109             LDCommData& cdata = stats->commData[cidx];
110             int senderPE, receiverPE;
111             if (cdata.from_proc())
112               senderPE = cdata.src_proc;
113             else {
114               int idx = stats->getHash(cdata.sender);
115               if (idx == -1) continue;    // sender has just migrated?
116               senderPE = stats->to_proc[idx];
117               CmiAssert(senderPE != -1);
118             }
119             CmiAssert(senderPE < count && senderPE >= 0);
120
121             // find receiver: point-to-point and multicast two cases
122             int receiver_type = cdata.receiver.get_type();
123             if (receiver_type == LD_PROC_MSG || receiver_type == LD_OBJ_MSG) {
124               if (receiver_type == LD_PROC_MSG)
125                 receiverPE = cdata.receiver.proc();
126               else  {  // LD_OBJ_MSG
127                 int idx = stats->getHash(cdata.receiver.get_destObj());
128                 if (idx == -1) continue;    // receiver has just been removed?
129                 receiverPE = stats->to_proc[idx];
130                 CmiAssert(receiverPE != -1);
131               }
132               CmiAssert(receiverPE < count && receiverPE >= 0);
133               if(senderPE != receiverPE)
134               {
135                 msgSentCount[senderPE] += cdata.messages;
136                 byteSentCount[senderPE] += cdata.bytes;
137                 msgRecvCount[receiverPE] += cdata.messages;
138                 byteRecvCount[receiverPE] += cdata.bytes;
139               }
140             }
141             else if (receiver_type == LD_OBJLIST_MSG) {
142               int nobjs;
143               LDObjKey *objs = cdata.receiver.get_destObjs(nobjs);
144               mcast_count ++;
145               CkVec<int> pes;
146               for (i=0; i<nobjs; i++) {
147                 int idx = stats->getHash(objs[i]);
148                 CmiAssert(idx != -1);
149                 if (idx == -1) continue;    // receiver has just been removed?
150                 receiverPE = stats->to_proc[idx];
151                 CmiAssert(receiverPE < count && receiverPE >= 0);
152                 int exist = 0;
153                 for (int p=0; p<pes.size(); p++) 
154                   if (receiverPE == pes[p]) { exist=1; break; }
155                 if (exist) continue;
156                 pes.push_back(receiverPE);
157                 if(senderPE != receiverPE)
158                 {
159                 msgSentCount[senderPE] += cdata.messages;
160                 byteSentCount[senderPE] += cdata.bytes;
161                 msgRecvCount[receiverPE] += cdata.messages;
162                 byteRecvCount[receiverPE] += cdata.bytes;
163                 }
164               }
165             }
166           }   // end of for
167           if (_lb_args.debug())
168              CkPrintf("Number of MULTICAST: %d\n", mcast_count);
169
170           // now for each processor, add to its load the send and receive overheads
171           for(i = 0; i < count; i++)
172           {
173                 double comload = msgRecvCount[i]  * PER_MESSAGE_RECV_OVERHEAD +
174                               msgSentCount[i]  * alpha +
175                               byteRecvCount[i] * PER_BYTE_RECV_OVERHEAD +
176                               byteSentCount[i] * beeta;
177                 peLoads[i] += comload;
178                 if (comLoads) comLoads[i] += comload;
179                 msgCount += msgRecvCount[i] + msgSentCount[i];
180                 msgBytes += byteRecvCount[i] + byteSentCount[i];
181           }
182           delete [] msgRecvCount;
183           delete [] msgSentCount;
184           delete [] byteRecvCount;
185           delete [] byteSentCount;
186         }
187 #endif
188 }
189
190 void LBInfo::print()
191 {
192   int i;  
193   double minLoad, maxLoad, maxProcObjLoad, avgProcObjLoad, maxComLoad, sum, average, avgComLoad;
194   double avgBgLoad;
195   int max_loaded_proc = 0;
196   sum = .0;
197   sum = minLoad = maxLoad = peLoads[0];
198   avgProcObjLoad = maxProcObjLoad = objLoads[0];
199   avgComLoad = maxComLoad = comLoads[0];
200   avgBgLoad = bgLoads[0];
201   for (i = 1; i < numPes; i++) {
202     double load = peLoads[i];
203     if (load>maxLoad) {
204       maxLoad=load;
205       max_loaded_proc = i;
206     } else if (peLoads[i]<minLoad) minLoad=load;
207     if (objLoads[i]>maxProcObjLoad) maxProcObjLoad = objLoads[i];
208     if (comLoads[i]>maxComLoad) maxComLoad = comLoads[i];
209     sum += load;
210     avgProcObjLoad += objLoads[i];
211     avgBgLoad += bgLoads[i];
212     avgComLoad += comLoads[i];
213   }
214   average = sum/numPes;
215   avgProcObjLoad /= numPes; 
216   avgBgLoad /= numPes; 
217   avgComLoad /= numPes;
218   CmiPrintf("The processor loads are: \n");
219   CmiPrintf("PE   (Total Load) (Obj Load) (Comm Load) (BG Load)\n");
220   if (_lb_args.debug() > 3)
221     for(i = 0; i < numPes; i++)
222       CmiPrintf("%-4d %10f %10f %10f %10f\n", i, peLoads[i], objLoads[i], comLoads[i], bgLoads[i]);
223   CmiPrintf("max: %10f %10f %10f\n", maxLoad, maxProcObjLoad, maxComLoad);
224   CmiPrintf("Min : %f Max : %f  Average: %f AvgBgLoad: %f\n", minLoad, maxLoad, average, avgBgLoad);
225   CmiPrintf("ProcObjLoad  Max : %f  Average: %f\n", maxProcObjLoad, avgProcObjLoad);
226   CmiPrintf("CommLoad  Max : %f  Average: %f\n", maxComLoad, avgComLoad);
227   CmiPrintf("[%d] is Maxloaded maxload: %f ObjLoad %f BgLoad %f\n",
228                         max_loaded_proc, peLoads[max_loaded_proc], objLoads[max_loaded_proc], bgLoads[max_loaded_proc]);
229   // the min and max object (calculated in getLoadInfo)
230   CmiPrintf("MinObj : %f  MaxObj : %f\n", minObjLoad, maxObjLoad, average);
231   CmiPrintf("Non-local comm: %d msgs %lld bytes\n", msgCount, msgBytes);
232 }
233
234 void LBInfo::getSummary(LBRealType &maxLoad, LBRealType &maxCpuLoad, LBRealType &totalLoad)
235 {
236   totalLoad = maxLoad = peLoads[0];
237   maxCpuLoad = objLoads[0];
238   for (int i = 1; i < numPes; i++) {
239     LBRealType load = peLoads[i];
240     if (load>maxLoad) maxLoad=load;
241     LBRealType cpuload = objLoads[i];
242     if (cpuload>maxCpuLoad) maxCpuLoad=cpuload;
243     totalLoad += load;
244   }
245 }
246
247 ////////////////////////////////////////////////////////////////////////////
248
249 LBSimulation::LBSimulation(int numPes_) : lbinfo(numPes_), numPes(numPes_)
250 {
251 }
252
253 LBSimulation::~LBSimulation()
254 {
255 }
256
257 void LBSimulation::reset()
258 {
259   lbinfo.clear();
260 }
261
262 void LBSimulation::SetProcessorLoad(int pe, double load, double bgload)
263 {
264         CkAssert(0 <= pe && pe < numPes);
265         lbinfo.peLoads[pe] = load;
266         lbinfo.bgLoads[pe] = bgload;
267 }
268
269 void LBSimulation::PrintSimulationResults()
270 {
271   lbinfo.print();
272 }
273
274 void LBSimulation::PrintDecisions(LBMigrateMsg *m, char *simFileName,
275                                   int peCount)
276 {
277   char *resultFile = (char *)malloc((strlen(simFileName) +
278                                      strlen("results") + 2)*sizeof(char));
279   sprintf(resultFile,"%s.results", simFileName);
280   FILE *f = fopen(resultFile, "w");
281   fprintf(f, "%d %d\n", peCount, m->n_moves); // header
282   for (int i=0; i<m->n_moves; i++) {
283     fprintf(f, "%d ", m->moves[i].obj.id.id[0]);
284     fprintf(f, "%d ", m->moves[i].obj.id.id[1]);
285     fprintf(f, "%d ", m->moves[i].obj.id.id[2]);
286     fprintf(f, "%d ", m->moves[i].obj.id.id[3]);
287     fprintf(f, "%d\n",m->moves[i].to_pe);
288   }
289 }
290
291 void LBSimulation::PrintDifferences(LBSimulation *realSim, BaseLB::LDStats *stats)
292 {
293   LBRealType *peLoads = lbinfo.peLoads;
294   LBRealType *realPeLoads = realSim->lbinfo.peLoads;
295
296   // the number of procs during the simulation and the real execution must be checked by the caller!
297   int i;
298   // here to print the differences between the predicted (this) and the real (real)
299   CmiPrintf("Differences between predicted and real balance:\n");
300   CmiPrintf("PE   (Predicted Load) (Real Predicted)  (Difference)  (Real CPU)  (Prediction Error)\n");
301   for(i = 0; i < numPes; ++i) {
302     CmiPrintf("%-4d %13f %16f %15f %12f %14f\n", i, peLoads[i], realPeLoads[i], peLoads[i]-realPeLoads[i],
303               stats->procs[i].total_walltime-stats->procs[i].idletime, realPeLoads[i]-(stats->procs[i].total_walltime-stats->procs[i].idletime));
304   }
305 }