2d37ab6d18e67a483ad3505bbb8a327075ff52aa
[charm.git] / examples / bigsim / tools / rewritelog / interpolatelog.C
1 /*
2
3     @file interpolatelog.C
4
5         @author: Isaac Dooley
6         email : idooley2@uiuc.edu
7         date  : Jan 2007
8
9     This uses the gsl library for least-square fitting. Gnu Scientific Library is available under GPL
10
11     Currently we hard code in two parameters some places.
12
13 */
14
15 #include "blue.h"
16 #include "blue_impl.h"
17 #include "blue.h"
18 #include "blue_impl.h"
19 #include "blue_types.h"
20 #include "bigsim_logs.h"
21 #include "assert.h"
22 #include <sys/stat.h>
23 #include <sys/types.h>
24
25 #include <EventInterpolator.h>
26
27 #include <string>
28 #include <iostream>
29 #include <fstream>
30 #include <map>
31 #include <utility> // for std::pair
32 #include <vector>
33
34 #define OUTPUTDIR "newtraces/"
35 #define CYCLE_TIMES_FILE "nopme"
36 #define sec_per_cycle 0.00000000025
37
38 // Scale the duration of all unknown events by this factor
39 #define time_factor 0.2
40
41 // Set these for more output:
42 #define DEBUG
43 #undef PRINT_NEW_TIMES
44 #define WRITE_OUTPUT_FILES
45
46 // Needed to communicated with the bigsim file reading and writing routines:
47 extern BgTimeLineRec* currTline;
48 extern int currTlineIdx;
49
50
51 /** linearly map a point from an interval with sepcified bounds to a new interval linearly 
52     @return a value between new_lower and new_upper
53 */
54 double map_linearly_to_interval(double val, double old_lower, double old_upper, double new_lower, double new_upper){
55   double new_val;
56
57   if(val = old_lower)
58         new_val = new_lower;
59   else if(val = old_upper)
60         new_val = old_lower;
61   else
62         new_val = new_lower + ((val-old_lower)*(new_upper-new_lower))/(old_upper-old_lower);
63
64   assert(new_val <= new_upper);
65   assert(new_val >= new_lower);
66
67   return new_val;
68 }
69
70 int main()
71 {
72     // Load in Mambo Times
73     EventInterpolator interpolator(CYCLE_TIMES_FILE);
74
75     int totalProcs, numX, numY, numZ, numCth, numWth, numPes;
76         double ratio_sum=0.0;
77         unsigned long ratio_count= 0;
78         interpolator.printCoefficients();
79
80     // load bg trace summary file
81     printf("Loading bgTrace ... \n");
82     int status = BgLoadTraceSummary("bgTrace", totalProcs, numX, numY, numZ, numCth, numWth, numPes);
83     if (status == -1) exit(1);
84     printf("========= BgLog Version: %d ========= \n", bglog_version);
85     printf("Found %d (%dx%dx%d:%dw-%dc) emulated procs on %d real procs.\n", totalProcs, numX, numY, numZ, numWth, numCth, numPes);
86
87     int* allNodeOffsets = BgLoadOffsets(totalProcs,numPes);
88
89     printf("========= Loading All Logs ========= \n");
90
91     // load each individual trace file for each bg proc
92
93     unsigned found_event_count=0;
94     unsigned total_count=0;
95     bool negative_durations_occured = false;
96
97     printf("Loading bgTrace files ...\n");
98
99     // Create output directory
100     mkdir(OUTPUTDIR, 0777);
101
102
103     for (int fileNum=0; fileNum<numPes; fileNum++){
104         BgTimeLineRec *tlinerecs = new BgTimeLineRec[totalProcs/numPes];
105         int rec_count = 0;
106
107         for(int procNum=fileNum;procNum<totalProcs;procNum+=numPes){
108
109             BgTimeLineRec &tlinerec = tlinerecs[rec_count];
110             rec_count++;
111
112             currTline = &tlinerec;
113             currTlineIdx = procNum;
114             int fileNum = BgReadProc(procNum,numWth,numPes,totalProcs,allNodeOffsets,tlinerec);
115             CmiAssert(fileNum != -1);
116
117 #ifdef DEBUG
118         printf("Load log of BG proc %d from bgTrace%d... \n", procNum, fileNum);
119 #endif
120
121             BgTimeLine &timeLine = tlinerec.timeline; // Really a CkQ< BgTimeLog *>
122
123 #ifdef DEBUG
124             printf("%d entries in timeLine\n", timeLine.length());
125 #endif
126
127             // Scan through each event for this emulated processor
128             for(int j=0;j<timeLine.length();j++){
129                 BgTimeLog* timeLog = timeLine[j];
130                 std::string name(timeLog->name);
131                 total_count++;
132
133                 double old_start = timeLog->startTime;
134                 double old_end   = timeLog->endTime;
135                 double old_duration = old_end-old_start;
136
137                                 double old_bracket_start = -1.0;
138                                 double old_bracket_end;
139
140                                 double new_bracket_duration;
141                                 double new_other_duration;
142
143                                 int have_bracket_start=0;
144                                 int have_bracket_end=0;
145
146                                 double begin_piece=0.0;
147                                 double middle_piece=old_duration;
148                                 double end_piece=0.0;
149
150                                 //                      assert(old_end > 0.0);
151                                 if(old_end > old_start){
152
153                                   // Look for BG_EVENT_PRINT 'events' inside this event.
154                                   for(int i=0;i<timeLog->evts.length();i++){
155                                         char *data = (char*)timeLog->evts[i]->data;
156                                         printf("Event ->%s<-\n",data);
157                                         if(strncmp(data,"startTraceBigSim",16)==0){
158                                           old_bracket_start = old_start+timeLog->evts[i]->rTime;
159                                           have_bracket_start = 1;
160                                           printf("\t\tfound startTraceBigSim!!!\n");
161                                         }
162                                         else if(strncmp(data,"endTraceBigSim",14)==0){
163                                           old_bracket_end = old_start+timeLog->evts[i]->rTime;
164                                           have_bracket_end = 1;  
165                                           printf("\t\tfound endTraceBigSim!!!\n");
166                                         }
167                                   }
168
169                                   // If we have bracketed timings, the middle part will be the old 
170                                   // bracketed time region, and the begin and end pieces will be non-zero                               
171                                   if(have_bracket_end && have_bracket_start){
172                                         begin_piece = old_bracket_start - old_start;
173                                         middle_piece = old_bracket_end - old_bracket_start;
174                                         end_piece = (old_end - old_start) - begin_piece - middle_piece;
175                                   }
176
177
178                                   // If this event occurs in the paramerter file and cycle-accurate simulations, use that data to predict its runtime
179                                 
180                                   if( interpolator.haveNewTiming(procNum,timeLog->seqno) ) {
181                                         middle_piece = interpolator.getNewTiming(procNum,timeLog->seqno) * sec_per_cycle;
182                                         found_event_count ++;
183                                   }
184                                   // If event is not in parameter file then we just scale its duration by a simple constant
185                                   else {
186                                         middle_piece = middle_piece*time_factor ;
187                                   }
188
189                                 
190                                   if(middle_piece < 0.0) {
191                                         middle_piece=0.0;
192                                         negative_durations_occured=true;
193                                   }
194
195                                   // Scale the begin and end pieces by time_factor;
196                                   begin_piece = begin_piece*time_factor;
197                                   end_piece = end_piece*time_factor;
198
199                                   assert(begin_piece >= 0.0);
200                                   assert(middle_piece >= 0.0);
201                                   assert(end_piece >= 0.0);
202
203                                   double new_start    = old_start;
204                                   double new_end      = new_start + begin_piece + middle_piece + end_piece;
205                                   double new_duration =             begin_piece + middle_piece + end_piece;
206
207                                   timeLog->startTime = new_start;
208                                   timeLog->endTime   = new_end;
209                                   timeLog->execTime  = new_duration;
210
211                                   double new_bracket_start = new_start+begin_piece;
212                                   double new_bracket_end = new_start+begin_piece+middle_piece;
213
214
215 #ifdef PRINT_NEW_TIMES
216                                   printf("Rewriting duration of event %d name=%s from [%.10lf , %.10lf] (%.10lf) to [%.10lf , %.10lf] (%.10lf) ratio=%.10lf\n", j, timeLog->name, old_start,old_end,old_end-old_start,new_start,new_end,new_end-new_start,(old_end-old_start)/(new_end-new_start));
217 #endif
218                                 
219                                   double ratio = (old_duration)/(new_duration);
220                                   if(ratio >= 0.5 && ratio <= 50.0){
221                                         ratio_sum += ratio;
222                                         ratio_count ++;
223                                   }
224
225                                   // Rewrite times of messages sent from this event
226                                   for(int m=0;m<timeLog->msgs.length();m++){
227                                         double old_send = timeLog->msgs[m]->sendTime;
228                                         double new_send;
229                                   
230                                         assert(old_send <= old_end);
231                                         assert(old_send >= old_start);
232                                   
233                                         // We have three places where the message is coming from
234                                         // We linearly map the value into the beginning, middle, or end piece
235                                         if(old_send < old_bracket_start){
236                                           new_send = map_linearly_to_interval(old_send, old_start,old_bracket_start,new_start,new_bracket_start);
237                                         } 
238                                         else if(old_send < old_bracket_end){
239                                           new_send = map_linearly_to_interval(old_send, old_bracket_start,old_bracket_end,new_bracket_start,new_bracket_end);
240                                         }
241                                         else {
242                                           new_send = map_linearly_to_interval(old_send, old_bracket_end,old_end,new_bracket_end,new_end);
243                                         }                                 
244                                   
245                                         timeLog->msgs[m]->sendTime = new_send;
246                                   
247 #ifdef PRINT_NEW_TIMES
248                                         printf("pe=%d changing message %d send time from %.10lf to %.10lf\n", procNum, m, old_send, new_send);
249 #endif
250                                   
251                                         assert(new_send <= new_end);
252                                         assert(new_send >= new_start);                            
253                                   
254                                   }
255                                 }
256                                 
257             }
258                         
259
260         }
261
262 #ifdef WRITE_OUTPUT_FILES
263             // Write out the file
264             cout << "writing " << rec_count << " simulated processors to this bgTrace file" << endl;
265             BgWriteTimelines(fileNum,tlinerecs,rec_count,numWth,OUTPUTDIR);
266 #endif
267         delete[] tlinerecs;
268
269     }
270
271
272     if(negative_durations_occured){
273           cerr << "======================  WARNING ======================" << endl;
274           cerr << "||  One or more new durations were less than zero. \n||  This probably means your model or input times are \n||  not good enough." << endl;
275           cerr << "======================================================" << endl;
276     }
277
278     interpolator.printMinInterpolatedTimes();
279
280     printf("Writing new bgTrace files ...\n");
281
282         printf("average duration ratio: %.15lf\n", ratio_sum / (double)ratio_count);
283
284 #ifdef WRITE_OUTPUT_FILES
285     // Write out the timelines to the same number of files as we started with.
286     BgWriteTraceSummary(totalProcs, numPes, numX, numY, numZ, numCth, numWth, OUTPUTDIR);
287 #endif
288
289     delete [] allNodeOffsets;
290
291     std::cout << "Of the " << total_count << " events found in the bgTrace files, " << found_event_count << " were found in the param files" << endl;
292
293     interpolator.printMatches();
294
295     std::cout << "End of program" << std::endl;
296
297 }
298