e909ee61a6c08b0550d0d5083a2134744d186396
[charm.git] / examples / bigsim / tools / rewritelog / EventInterpolator.C
1
2 #include <EventInterpolator.h>
3
4 #define DEBUG
5
6 using namespace std;
7
8 int EventInterpolator::numCoefficients(const string &funcname){
9 // We create a dummy input stringstream and pass it to parseParameters.
10 // Then we count how many parameters that function creates
11     string temp("0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0");
12     istringstream temp2(temp);
13     return parseParameters(funcname,temp2,false).second.size();
14 }
15
16
17 int distance(int i1, int i2, int i3, int i4, int i5, int i6){
18     int x1 =(abs(13+i1-i4)%13)*4;
19     int x2 =(abs(13+i4-i1)%13)*4;
20     int x = min(x1,x2);
21
22     int y1 =(abs(6+i2-i5)%6)*2;
23     int y2 =(abs(6+i5-i2)%6)*2;
24     int y = min(y1,y2);
25
26     int z1 =(abs(4+i3-i6)%4)*1;
27     int z2 =(abs(4+i6-i3)%4)*1;
28     int z = min(z1,z2);
29
30     return x+y+z;
31
32 }
33
34 pair<int,vector<double> > EventInterpolator::parseParameters(const string &funcname, istringstream &param_stream, const bool log){
35     double temp;
36     return parseParameters(funcname,param_stream,temp, log);
37 }
38
39
40 pair<int,vector<double> > EventInterpolator::parseParameters(const string &funcname, istringstream &line, double &time, const bool log){
41     vector<double> params;
42     int category=0;
43
44     if( funcname == string("calc_self_energy_merge_fullelect") ||
45         funcname == string("calc_pair_energy_merge_fullelect") ||
46         funcname == string("calc_self_merge_fullelect") ||
47         funcname == string("calc_pair_merge_fullelect") ||
48         funcname == string("calc_self") ||
49         funcname == string("calc_pair") ||
50         funcname == string("calc_self_energy") ||
51         funcname == string("calc_pair_energy") ){
52
53         double d1,d2,d3,d4,d5,d6,d7,d8,d9, t1;
54         int i1,i2,i3,i4,i5,i6;
55
56         line >> d1 >> d2 >> i1 >> i2 >> i3 >> i4 >> i5 >> i6 >>
57                 d3 >> d4 >> d5 >> d6 >> d7 >> d8 >> t1;
58
59         if(log)
60             log1 << funcname << "\t" << t1 << "\t"  << d1  << "\t" << d2 << "\t"  << d3  << "\t" << d4  << "\t" << d5 << "\t"  << d6  << "\t" << d7  << "\t" << d8 << "\t" << i1  << "\t" << i2 << "\t"  << i3  << "\t" << i4  << "\t" << i5 << "\t"  << i6 << "\t" << distance(i1,i2,i3,i4,i5,i6) << endl;
61
62         params.push_back( 1.0);
63
64 //         params.push_back( 1.0 / distance );
65         params.push_back( d3 );
66         params.push_back( d4 );
67         params.push_back( d5 );
68                 //        params.push_back( d2 );
69                 //        params.push_back( d3 );
70                 //        params.push_back( d4 );
71         params.push_back( min(d1,d2)*d1*d2 );
72         params.push_back( d1*d2 );
73
74         category = distance(i1,i2,i3,i4,i5,i6 );
75
76         time = t1;
77     }
78     else if(funcname == string("angle") || funcname == string("dihedrals")){
79         double d1, d2, t1;
80         line >> d1 >> d2 >> t1;
81
82         if(log)
83             log1 << funcname << "\t" << t1 << "\t"  << d1  << "\t" << d2 << endl;
84
85         params.push_back( 1.0);
86         params.push_back( d2 );
87         params.push_back( d2*d2 );
88
89         time = t1;
90
91     }
92     else if(funcname == string("*integrate*")){
93         double d1, d2, d3, d4, d5, d6, d7, t1;
94         line >> d1 >> d2 >> d3 >> d4 >> d5 >> d6 >> d7 >> t1;
95
96         if(log)
97             log1 << funcname << "\t" << t1 << "\t" << d1 << "\t" << d2 << "\t" << d3 << "\t" << d4 << "\t" << d5 << "\t" << d6 << "\t" << d7 << endl;
98
99         params.push_back( 1.0);
100         params.push_back( d2 );
101         params.push_back( d2*d2 );
102         time = t1;
103
104     }
105     else {
106         cerr << "FATAL ERROR: Don't know how to read parameters for function " << funcname << endl;
107         throw new runtime_error("unknown function");
108     }
109
110     return pair<int,vector<double> >(category,params);
111 }
112
113
114
115
116
117 EventInterpolator::EventInterpolator(char *table_filename){
118     exact_matches=0;
119     exact_positive_matches=0;
120     approx_matches=0;
121     approx_positive_matches=0;
122
123         log1.open("log1");
124
125     cout << "Loading timings file: " << table_filename << endl;
126     ifstream accurateTimeTable(table_filename);
127     if(! accurateTimeTable.good() ){
128         cerr << "FATAL ERROR: Couldn't open file(perhaps it doesn't exist): " << table_filename << endl;
129         throw new runtime_error("missing file");
130     }
131
132
133     // First pass, scan through cycle accurate time file to count
134     // how many samples there are for each function
135     while(accurateTimeTable.good()){
136         string line_s;
137         getline(accurateTimeTable,line_s);
138         istringstream line(line_s);
139
140         string temp("");
141         while(temp != string("TRACEBIGSIM") && line.good() && accurateTimeTable.good() ){
142             line >> temp;
143         }
144         line >> temp; // gobble up one more worthless bit of input line
145
146         if(line.good() && accurateTimeTable.good()){
147             string funcname;
148             line >> funcname;
149
150                         double time;
151                         fullParams params = parseParameters(funcname,line,time,false);
152             funcIdentifier func(funcname,params.first);
153             sample_count[func]++;
154         }
155     }
156
157     // Create a gsl interpolator workspace for each event/function
158     for(map<funcIdentifier,unsigned long>::iterator i=sample_count.begin(); i!=sample_count.end();++i){
159         funcIdentifier func = (*i).first;
160         unsigned long samples = (*i).second;
161         cout << "     > " << func.first << "," << func.second << " has " << samples << " sampled timings" << endl;
162
163         if(samples < numCoefficients(func.first) ){
164             cerr << "FATAL ERROR: Not enough input timing samples for " << func.first << "," << func.second << " which has " << numCoefficients(func.first) << " coefficients" << endl;
165             throw new runtime_error("samples < numCoefficients");
166         }
167         else {
168             work[func] = gsl_multifit_linear_alloc(samples,numCoefficients(func.first));
169             X[func] = gsl_matrix_alloc (samples,numCoefficients(func.first));
170             y[func] = gsl_vector_alloc (samples);
171             c[func] = gsl_vector_alloc(numCoefficients(func.first));
172             cov[func] = gsl_matrix_alloc(numCoefficients(func.first),numCoefficients(func.first));
173
174             for(int i=0;i<numCoefficients(func.first);++i){
175                 gsl_vector_set(c[func],i,1.0);
176             }
177
178         }
179     }
180
181     accurateTimeTable.close();
182     ifstream accurateTimeTable2(table_filename);
183
184 #ifdef WRITESTATS
185     ofstream statfile("stats-out");
186 #endif
187
188     // Second pass, scan through cycle accurate time file
189     while(accurateTimeTable2.good()){
190         string line_s;
191         getline(accurateTimeTable2,line_s);
192         istringstream line(line_s);
193
194         string temp("");
195         while(temp != string("TRACEBIGSIM") && line.good() && accurateTimeTable2.good() ){
196             line >> temp;
197         }
198         line >> temp; // gobble up one more worthless bit of input line
199
200         if(line.good() && accurateTimeTable2.good()){
201             string funcname;
202             line >> funcname;
203
204             double time;
205             fullParams params = parseParameters(funcname,line,time,false);
206
207             funcIdentifier func(funcname,params.first);
208
209             unsigned i = Xcount[func] ++;
210             gsl_matrix * x = X[func];
211             accurateTimings[pair<funcIdentifier,vector<double> >(func,params.second)]=time;
212
213 #ifdef WRITESTATS
214             statfile << funcname << "\t" << time << endl;
215 #endif
216
217             for(int param_index=0;param_index<params.second.size();++param_index){
218                 gsl_matrix_set(x,i,param_index, params.second[param_index]);
219             }
220             gsl_vector_set(y[func],i,time);
221
222         }
223     }
224
225 #ifdef WRITESTATS
226     statfile.close();
227 #endif
228
229     // Perform a sanity check now
230
231     for(map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i=work.begin();i!=work.end();++i){
232         if(sample_count[(*i).first]!=Xcount[(*i).first]){
233           cerr << "FATAL ERROR: sanity check failed: " << sample_count[(*i).first] << "!=" << Xcount[(*i).first] << "  :(" << endl;
234        throw new runtime_error("sanity check failed");
235         }
236     }
237
238     cout << "Performing Least Squared Fit to sampled time data" << endl;
239
240     //  Now do Least Square Fit: Find C where y=Xc
241     map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i;
242     for(i=work.begin();i!=work.end();++i){
243         funcIdentifier func = (*i).first;
244         assert(! gsl_multifit_linear(X[func],y[func],c[func],cov[func],&chisqr[func],work[func]));
245         gsl_matrix_free(X[func]);
246         gsl_vector_free(y[func]);
247         cout << "     > " << func.first << "," << func.second << " has chisqr=" << chisqr[func] << endl;
248     }
249
250
251
252     // Load in Parameter File which maps event id to function name and parameters
253     cout << "Loading parameter files" << endl;
254
255     for(int i=0;i<102400;++i){
256         char name[512];
257         sprintf(name,"param.%d",i);
258         ifstream parameterEventTable(name);
259
260         if(parameterEventTable.good()){
261 #ifdef DEBUG
262             cout << "     >  Loading " << name << endl;
263 #endif
264
265             while(parameterEventTable.good()){
266                 string line_s;
267                 getline(parameterEventTable,line_s);
268                 istringstream line(line_s);
269
270                 if(parameterEventTable.good()){
271                     string t1, t2;
272                     string funcname;
273                     unsigned eventid;
274
275                     line >> eventid;
276                     line >> t1 >> t2;
277                     line >> funcname;
278
279                     if(t1 == string("TRACEBIGSIM")){
280                         fullParams params = parseParameters(funcname,line,false);
281                         funcIdentifier func(funcname,params.first);
282                         Xcount[func] ++;
283                         eventparams[pair<unsigned,unsigned>(i,eventid)] = pair<funcIdentifier,vector<double> >(func,params.second);
284                     }
285                 }
286             }
287
288         }
289         else{ // file was no good
290             break;
291         }
292
293         parameterEventTable.close();
294     }
295 }
296
297
298
299 bool EventInterpolator::haveExactTime(const unsigned pe, const unsigned eventid){
300     return haveExactTime(eventparams[pair<unsigned,unsigned>(pe,eventid)]);
301 }
302
303 bool EventInterpolator::haveExactTime(const pair<funcIdentifier,vector<double> > &p) {
304     return haveExactTime(p.first,p.second);
305 }
306
307 bool EventInterpolator::haveExactTime(const funcIdentifier& func, const vector<double> &p){
308     return (accurateTimings.find(pair<funcIdentifier,vector<double> >(func,p)) != accurateTimings.end());
309 }
310
311 double EventInterpolator::lookupExactTime(const unsigned pe, const unsigned eventid){
312     return lookupExactTime(eventparams[pair<unsigned,unsigned>(pe,eventid)]);
313 }
314
315 double EventInterpolator::lookupExactTime(const pair<funcIdentifier,vector<double> > &p) {
316     return lookupExactTime(p.first,p.second);
317 }
318
319 double EventInterpolator::lookupExactTime(const funcIdentifier& func, const vector<double> &p){
320     double val = accurateTimings[pair<funcIdentifier,vector<double> >(func,p)];
321     exact_matches++;
322     if(val>=0.0)
323         exact_positive_matches++;
324         else
325           cout << "exact negative match = " << val << endl;
326     return val;
327 }
328
329 /** If we have a parameterfile entry for the requested pe,eventid pair */
330 double EventInterpolator::haveNewTiming(const unsigned pe, const unsigned eventid) {
331     return eventparams.find( pair<unsigned,unsigned>(pe,eventid) ) != eventparams.end();
332 }
333
334 double EventInterpolator::predictTime(const unsigned pe, const unsigned eventid) {
335     return predictTime(eventparams[pair<unsigned,unsigned>(pe,eventid)]);
336 }
337
338 double EventInterpolator::predictTime(const pair<funcIdentifier,vector<double> > &p) {
339     return predictTime(p.first,p.second);
340 }
341
342 bool EventInterpolator::canInterpolateFunc(const funcIdentifier& func){
343     return (work.find(func) != work.end());
344 }
345
346
347 double EventInterpolator::getNewTiming(const unsigned pe, const unsigned eventid){
348   if(haveExactTime(pe,eventid) )
349         return lookupExactTime(pe,eventid);
350   else
351         return predictTime(pe,eventid);
352 }                         
353
354 double EventInterpolator::predictTime(const funcIdentifier &func, const vector<double> &params) {
355
356     // check name
357     if(!canInterpolateFunc(func)){
358         cerr << "FATAL ERROR: function name not found in cycle accurate timing file: " << func.first << "," << func.second << endl;
359        throw new runtime_error("function name not found");
360     }
361
362     // Estimate time for a given set of parameters p
363     gsl_vector *desired_params;
364
365     desired_params = gsl_vector_alloc(numCoefficients(func.first));
366     assert(numCoefficients(func.first)==params.size());
367
368     for(int i=0;i<params.size();++i){
369         gsl_vector_set(desired_params,i,params[i]);
370     }
371
372     double desired_time, desired_time_err;
373     assert(c[func]);
374     assert(cov[func]);
375     assert(! gsl_multifit_linear_est(desired_params,c[func],cov[func],&desired_time,&desired_time_err));
376
377     gsl_vector_free(desired_params);
378
379
380     if(min_interpolated_time.find(func) == min_interpolated_time.end())
381         min_interpolated_time[func] = desired_time;
382     else
383         min_interpolated_time[func] = min( min_interpolated_time[func], desired_time);
384
385     if(max_interpolated_time.find(func) == max_interpolated_time.end())
386         max_interpolated_time[func] = desired_time;
387     else
388         max_interpolated_time[func] = max( max_interpolated_time[func], desired_time);
389
390
391     approx_matches++;
392     if(desired_time>=0.0)
393         approx_positive_matches++;
394
395 //    gsl_vector_free(desired_params);
396
397
398     return desired_time;
399 }
400
401
402 void EventInterpolator::printMinInterpolatedTimes(){
403
404     cout << "The following functions were interpolated(as opposed to approximated:" << endl;
405
406     for(map<funcIdentifier,double>::iterator i=min_interpolated_time.begin();i!=min_interpolated_time.end();++i){
407         cout << "   > min predicted/interpolated time for function " << (*i).first.first << "," << (*i).first.second << " is " << (*i).second << " cycles " << endl;
408     }
409     for(map<funcIdentifier,double>::iterator i=max_interpolated_time.begin();i!=max_interpolated_time.end();++i){
410         cout << "   > max predicted/interpolated time for function " << (*i).first.first << "," << (*i).first.second << " is " << (*i).second << " cycles " << endl;
411     }
412
413     cout << endl;
414 }
415
416 void EventInterpolator::printMatches(){
417     cout << "    > Exact lookup = " << exact_matches << " (" << exact_positive_matches << " positive)" << endl;
418     cout << "    > Approximated = " << approx_matches << " (" << approx_positive_matches << " positive)" << endl;
419     cout << "    > Total        = " << approx_matches+exact_matches <<  " (" << exact_positive_matches+approx_positive_matches << " positive)" << endl;
420 }
421
422 void EventInterpolator::printCoefficients(){
423
424     for(map<funcIdentifier,gsl_vector*>::iterator i=c.begin();i!=c.end();++i){
425         cout << "    > Coefficients for function " << (*i).first.first << "," << (*i).first.second << " :" << endl;
426         for(int j=0; j < ((*i).second)->size; ++j){
427             cout << "    >    " << j << " is " << gsl_vector_get ((*i).second, j) << endl;
428         }
429     }
430
431 }
432
433
434
435
436 /** Free the gsl arrays and workspaces */
437 EventInterpolator::~EventInterpolator(){
438     map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i;
439     for(i=work.begin();i!=work.end();++i){
440         const funcIdentifier &func = (*i).first;
441         gsl_multifit_linear_free(work[func]);
442         gsl_matrix_free(cov[func]);
443         gsl_vector_free(c[func]);
444     }
445         log1.close();
446 }
447
448
449
450