7c077726b0ef4afbf0e3360efeaaac42955255b5
[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 */
12
13 #include "blue.h"
14 #include "blue_impl.h"
15 #include "blue.h"
16 #include "blue_impl.h"
17 #include "blue_types.h"
18 #include "bigsim_logs.h"
19 #include "assert.h"
20 #include <sys/stat.h>
21 #include <sys/types.h>
22
23 #include <EventInterpolator.h>
24
25 #include <string>
26 #include <iostream>
27 #include <fstream>
28 #include <map>
29 #include <utility> // for std::pair
30 #include <vector>
31
32 #define KEEP_RATIO 1.0
33
34 #define OUTPUTDIR "newtraces-keep1.0/"
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 //#define time_factor (1.0/4.418)
41 #define time_factor (1.0/6.05)
42
43 // Set these for more output:
44 //#define DEBUG
45 #undef PRINT_NEW_TIMES
46 #define WRITE_OUTPUT_FILES
47
48 // Needed to communicated with the bigsim file reading and writing routines:
49 extern BgTimeLineRec* currTline;
50 extern int currTlineIdx;
51
52
53 /** linearly map a point from an interval with sepcified bounds to a new interval linearly
54     @return a value between new_lower and new_upper
55 */
56 double map_linearly_to_interval(double val, double old_lower, double old_upper, double new_lower, double new_upper){
57   double new_val;
58
59   if(val = old_lower)
60         new_val = new_lower;
61   else if(val = old_upper)
62         new_val = old_lower;
63   else
64         new_val = new_lower + ((val-old_lower)*(new_upper-new_lower))/(old_upper-old_lower);
65
66   assert(new_upper >= new_lower);
67   assert(new_val <= new_upper);
68   assert(new_val >= new_lower);
69
70   assert(old_upper >= old_lower);
71   assert(val <= old_upper);
72   assert(val >= old_lower);
73
74   return new_val;
75 }
76
77 int main()
78 {
79     // Load in Mambo Times
80     EventInterpolator interpolator(CYCLE_TIMES_FILE, KEEP_RATIO);
81
82     int totalProcs, numX, numY, numZ, numCth, numWth, numPes;
83         double ratio_sum=0.0;
84         unsigned long ratio_count= 0;
85
86         double ratio_bracketed_sum=0.0;
87         unsigned long ratio_bracketed_count = 0;
88
89         double old_times_sum=0.0;
90         double old_bracketed_times_sum=0.0;
91         double new_bracketed_times_sum=0.0;
92
93         ofstream of_ratio_all("ratio_all");
94         ofstream of_ratio_bracketed("ratio_bracketed");
95
96         interpolator.printCoefficients();
97
98     // load bg trace summary file
99     printf("Loading bgTrace ... \n");
100     int status = BgLoadTraceSummary("bgTrace", totalProcs, numX, numY, numZ, numCth, numWth, numPes);
101     if (status == -1) exit(1);
102     printf("========= BgLog Version: %d ========= \n", bglog_version);
103     printf("Found %d (%dx%dx%d:%dw-%dc) emulated procs on %d real procs.\n", totalProcs, numX, numY, numZ, numWth, numCth, numPes);
104
105     int* allNodeOffsets = BgLoadOffsets(totalProcs,numPes);
106
107     printf("========= Loading All Logs ========= \n");
108
109     // load each individual trace file for each bg proc
110
111     unsigned found_event_count=0;
112     unsigned total_count=0;
113     bool negative_durations_occured = false;
114
115     printf("Loading bgTrace files ...\n");
116
117     // Create output directory
118     mkdir(OUTPUTDIR, 0777);
119
120
121     for (int fileNum=0; fileNum<numPes; fileNum++){
122         BgTimeLineRec *tlinerecs = new BgTimeLineRec[totalProcs/numPes+1];
123         int rec_count = 0;
124
125         for(int procNum=fileNum;procNum<totalProcs;procNum+=numPes){
126
127             BgTimeLineRec &tlinerec = tlinerecs[rec_count];
128             rec_count++;
129
130             currTline = &tlinerec;
131             currTlineIdx = procNum;
132             int fileNum = BgReadProc(procNum,numWth,numPes,totalProcs,allNodeOffsets,tlinerec);
133             CmiAssert(fileNum != -1);
134
135 #ifdef DEBUG
136         printf("Load log of BG proc %d from bgTrace%d... \n", procNum, fileNum);
137 #endif
138
139             BgTimeLine &timeLine = tlinerec.timeline; // Really a CkQ< BgTimeLog *>
140
141 #ifdef DEBUG
142             printf("%d entries in timeLine\n", timeLine.length());
143 #endif
144
145             // Scan through each event for this emulated processor
146             for(int j=0;j<timeLine.length();j++){
147                 BgTimeLog* timeLog = timeLine[j];
148                 std::string name(timeLog->name);
149                 total_count++;
150
151                 double old_start = timeLog->startTime;
152                 double old_end   = timeLog->endTime;
153                 double old_duration = old_end-old_start;
154
155                                 double old_bracket_start=0.0;
156                                 double old_bracket_end=0.0;
157
158                                 int have_bracket_start=0;
159                                 int have_bracket_end=0;
160
161                                 double begin_piece=0.0;
162                                 double middle_piece=old_duration;
163                                 double end_piece=0.0;
164
165                                 assert(old_duration >= 0.0);
166                                 assert(old_end > 0.0);
167
168                                 if(old_end > old_start){
169                                   old_times_sum += old_duration;
170
171                                   //FIXME: check only the right kind of events.
172
173                                   // Look for BG_EVENT_PRINT 'events' inside this event.
174                                   for(int i=0;i<timeLog->evts.length();i++){
175                                         char *data = (char*)timeLog->evts[i]->data;
176                                         if(strncmp(data,"startTraceBigSim",16)==0){
177                                           old_bracket_start = old_start+timeLog->evts[i]->rTime;
178                                           have_bracket_start = 1;
179                                         }
180                                         else if(strncmp(data,"endTraceBigSim",14)==0){
181                                           old_bracket_end = old_start+timeLog->evts[i]->rTime;
182                                           have_bracket_end = 1;
183                                         }
184                                   }
185
186                                   // If we have bracketed timings, the middle part will be the old
187                                   // bracketed time region, and the begin and end pieces will be non-zero
188                                   if(have_bracket_end && have_bracket_start){
189                                         begin_piece = old_bracket_start - old_start;
190                                         middle_piece = old_bracket_end - old_bracket_start;
191                                         end_piece = old_duration - begin_piece - middle_piece;
192                                         old_bracketed_times_sum += middle_piece;
193                                         assert(begin_piece >= 0.0);
194                                         assert(middle_piece >= 0.0);
195                                         assert(end_piece >= 0.0);
196                                   }
197                                   else{
198                                         old_bracket_start = old_start;
199                                         old_bracket_end = old_end;
200                                         assert(old_bracket_end - old_bracket_start >= 0.0);
201                                   }
202
203
204                                   // If this event occurs in the paramerter file and cycle-accurate simulations, use that data to predict its runtime
205
206                                   if( interpolator.haveNewTiming(procNum,timeLog->seqno) ) {
207                                         double old_middle_piece = middle_piece;
208                                         middle_piece = interpolator.getNewTiming(procNum,timeLog->seqno) * sec_per_cycle;
209                                         found_event_count ++;
210
211                                         double ratio =  old_middle_piece / middle_piece;
212                                         if(ratio > 1e-10 && ratio < 1e10){
213                                           ratio_bracketed_sum += ratio;
214                                           ratio_bracketed_count ++;
215                                           of_ratio_bracketed << ratio << endl;
216                                         }
217
218
219                                   }
220                                   // If event is not in parameter file then we just scale its duration by a simple constant
221                                   else {
222                                         middle_piece = middle_piece*time_factor ;
223                                   }
224
225
226                                   if(middle_piece < 0.0) {
227                                         middle_piece=0.0;
228                                         negative_durations_occured=true;
229                                   }
230
231                                   if(have_bracket_end && have_bracket_start){
232                                         new_bracketed_times_sum += middle_piece;
233                                   }
234
235                                   // Scale the begin and end pieces by time_factor;
236                                   begin_piece = begin_piece*time_factor;
237                                   end_piece = end_piece*time_factor;
238
239                                   assert(begin_piece >= 0.0);
240                                   assert(middle_piece >= 0.0);
241                                   assert(end_piece >= 0.0);
242
243                                   double new_start    = old_start;
244                                   double new_duration = begin_piece + middle_piece + end_piece;
245                                   double new_end      = new_start + new_duration;
246
247                                   timeLog->startTime = new_start;
248                                   timeLog->endTime   = new_end;
249                                   timeLog->execTime  = new_duration;
250
251                                   double new_bracket_start = new_start+begin_piece;
252                                   double new_bracket_end = new_start+begin_piece+middle_piece;
253
254
255 #ifdef PRINT_NEW_TIMES
256                                   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));
257 #endif
258
259                                   double ratio = (old_duration)/(new_duration);
260                                   if(ratio >= 1e-10 && ratio <= 1e10){
261                                         ratio_sum += ratio;
262                                         ratio_count ++;
263                                         of_ratio_all << ratio << endl;
264                                   }
265
266                                   // Rewrite times of messages sent from this event
267                                   for(int m=0;m<timeLog->msgs.length();m++){
268                                         double old_send = timeLog->msgs[m]->sendTime;
269                                         double new_send;
270
271                                         assert(old_send <= old_end);
272                                         assert(old_send >= old_start);
273
274                                         // We have three places where the message is coming from
275                                         // We linearly map the value into the beginning, middle, or end piece
276                                         if(old_send < old_bracket_start){
277                                           new_send = map_linearly_to_interval(old_send, old_start,old_bracket_start,new_start,new_bracket_start);
278                                         }
279                                         else if(old_send < old_bracket_end){
280                                           new_send = map_linearly_to_interval(old_send, old_bracket_start,old_bracket_end,new_bracket_start,new_bracket_end);
281                                         }
282                                         else {
283                                           new_send = map_linearly_to_interval(old_send, old_bracket_end,old_end,new_bracket_end,new_end);
284                                         }
285
286                                         timeLog->msgs[m]->sendTime = new_send;
287
288 #ifdef PRINT_NEW_TIMES
289                                         printf("pe=%d changing message %d send time from %.10lf to %.10lf\n", procNum, m, old_send, new_send);
290 #endif
291
292                                         assert(new_send <= new_end);
293                                         assert(new_send >= new_start);
294
295                                   }
296                                 }
297
298             }
299
300
301         }
302
303 #ifdef WRITE_OUTPUT_FILES
304             // Write out the file
305             cout << "writing " << rec_count << " simulated processors to this bgTrace file" << endl;
306             BgWriteTimelines(fileNum,tlinerecs,rec_count,numWth,OUTPUTDIR);
307 #endif
308         delete[] tlinerecs;
309
310     }
311
312
313     if(negative_durations_occured){
314           cerr << "======================  WARNING ======================" << endl;
315           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;
316           cerr << "======================================================" << endl;
317     }
318
319     interpolator.printMinInterpolatedTimes();
320
321     printf("Writing new bgTrace files ...\n");
322
323         printf("average duration speedup(including unbracketed pieces): %.8lf\n", ratio_sum / (double)ratio_count);
324
325         printf("average bracketed speedup: %.8lf\n", ratio_bracketed_sum / (double)ratio_bracketed_count);
326
327         cout << "Sum of times of bracketed portions of input logs: " << old_bracketed_times_sum << endl;
328         cout << "Sum of times of bracketed portions of output logs: " << new_bracketed_times_sum << endl;
329
330
331
332 #ifdef WRITE_OUTPUT_FILES
333     // Write out the timelines to the same number of files as we started with.
334     BgWriteTraceSummary(totalProcs, numPes, numX, numY, numZ, numCth, numWth, OUTPUTDIR);
335 #endif
336
337     delete [] allNodeOffsets;
338
339     cout << "Of the " << total_count << " events found in the bgTrace files, " << found_event_count << " were found in the param files" << endl;
340
341     interpolator.printMatches();
342
343         cout << "The sum of all positive duration events from the original bgTrace files is: " << old_times_sum << endl;
344
345
346     cout << "End of program" << endl;
347
348 }
349