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