1 /* 2 This file is part of GNU APL, a free implementation of the 3 ISO/IEC Standard 13751, "Programming Language APL, Extended" 4 5 Copyright (C) 2008-2015 Dr. Jürgen Sauermann 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef __PERFORMANCE_HH_DEFINED__ 22 #define __PERFORMANCE_HH_DEFINED__ 23 24 #include <stdint.h> 25 26 #include <iostream> 27 28 #include "../config.h" 29 30 #if defined(PERFORMANCE_COUNTERS_WANTED) 31 32 # define PERFORMANCE_START(counter) const uint64_t counter = cycle_counter(); 33 # define PERFORMANCE_END(statistics, counter, len) \ 34 Performance::statistics.add_sample(cycle_counter() - counter, len); 35 # define CELL_PERFORMANCE_END(get_stat, counter, subseq) \ 36 { const uint64_t end = cycle_counter(); \ 37 CellFunctionStatistics * stat = get_stat; \ 38 if (stat) stat->add_sample(end - counter, subseq); } 39 40 #else 41 42 # define PERFORMANCE_START(counter) 43 # define PERFORMANCE_END(statistics, counter, len) 44 # define CELL_PERFORMANCE_END(get_stat, counter, subseq) 45 46 #endif 47 48 using namespace std; 49 50 //----------------------------------------------------------------------------- 51 /// performance statistics IDs 52 enum Pfstat_ID 53 { 54 PFS_MIN1 = 0, 55 PFS_MIN1_1 = PFS_MIN1 - 1, 56 #define perfo_1( id, ab, name, _thr) PFS_ ## id ## ab, 57 #define perfo_2(_id, _ab, name, _thr) 58 #define perfo_3(_id, _ab, name, _thr) 59 #define perfo_4(_id, _ab, name, _thr) 60 #include "Performance.def" 61 PFS_MAX1, 62 PFS_MAX1_1 = PFS_MAX1 - 1, 63 64 PFS_MIN2, 65 PFS_MIN2_1 = PFS_MIN2 - 1, 66 #define perfo_1(_id, _ab, name, _thr) 67 #define perfo_2( id, ab, name, _thr) PFS_ ## id ## ab, 68 #define perfo_3(_id, _ab, name, _thr) 69 #define perfo_4(_id, _ab, name, _thr) 70 #include "Performance.def" 71 PFS_MAX2, 72 PFS_MAX2_1 = PFS_MAX2 - 1, 73 74 PFS_MIN3, 75 PFS_MIN3_1 = PFS_MIN3 - 1, 76 #define perfo_1(_id, _ab, name, _thr) 77 #define perfo_2(_id, _ab, name, _thr) 78 #define perfo_3( id, ab, name, _thr) PFS_ ## id ## ab, 79 #define perfo_4( id, ab, name, _thr) PFS_ ## id ## ab, 80 #include "Performance.def" 81 PFS_MAX3, 82 PFS_MAX3_1 = PFS_MAX3 - 1, 83 84 PFS_SCALAR_B_overhead, 85 PFS_SCALAR_AB_overhead, 86 PFS_ALL 87 }; 88 //============================================================================= 89 /// one statistics for computing the mean and the variance of samples 90 class Statistics_record 91 { 92 public: 93 /// constructor Statistics_record()94 Statistics_record() { reset(); } 95 96 /// constructor Statistics_record(uint64_t cnt,uint64_t da,double da2)97 Statistics_record(uint64_t cnt, uint64_t da, double da2) 98 : count(cnt), 99 data(da), 100 data2(da2) 101 {} 102 103 /// reset record to count 0, mean 0, variance 0 reset()104 void reset() 105 { 106 count = 0; 107 data = 0; 108 data2 = 0; 109 } 110 111 /// add one sample add_sample(uint64_t val)112 void add_sample(uint64_t val) 113 { 114 ++count; 115 data += val; 116 data2 += val*val; 117 } 118 119 /// print count, data, and data2 120 void print(ostream & out); 121 122 /// write count, data, and data2 to file 123 void save_record(ostream & outf); 124 125 /// return the number of samples get_count() const126 uint64_t get_count() const 127 { return count; } 128 129 /// return the sum of samples get_sum() const130 uint64_t get_sum() const 131 { return data; } 132 133 /// return the average get_average() const134 uint64_t get_average() const 135 { return average(data, count); } 136 137 /// return the sum of squares get_sum2() const138 double get_sum2() const 139 { return data2; } 140 141 /// the average of \b count items with sum \b sum average(uint64_t sum,uint64_t count)142 static uint64_t average(uint64_t sum, uint64_t count) 143 { return count ? sum/count : 0; } 144 145 /// print num as 5 characters (digits, dot, and multiplier (k, m, g, ...) 146 static void print5(ostream & out, uint64_t num); 147 148 protected: 149 /// number of samples 150 uint64_t count; 151 152 /// sum of sample values 153 uint64_t data; 154 155 /// sum of squares of sample values 156 double data2; // can grow quickly! 157 }; 158 //============================================================================= 159 /// Base class for different kinds of statistics 160 class Statistics 161 { 162 public: 163 /// constructor Statistics(Pfstat_ID _id)164 Statistics(Pfstat_ID _id) 165 : id(_id) 166 {} 167 168 /// destructor 169 virtual ~Statistics(); 170 171 /// print statistics 172 virtual void print(ostream & out) = 0; 173 174 /// write statistics to file 175 virtual void save_data(ostream & outf, const char * perf_name) = 0; 176 177 /// reset \b this statistics 178 virtual void reset() = 0; 179 180 /// return the statistics for the first passes get_first_record() const181 virtual const Statistics_record * get_first_record() const 182 { return 0; } 183 184 /// return the statistics for the subsequent passes get_record() const185 virtual const Statistics_record * get_record() const 186 { return 0; } 187 188 /// return the name of \b this statistics get_name() const189 const char * get_name() const 190 { return get_name(id); } 191 192 /// return the name of the statistics with ID \b id 193 static const char * get_name(Pfstat_ID id); 194 195 protected: 196 /// the ID of \b this statistics 197 const Pfstat_ID id; 198 }; 199 //============================================================================= 200 /// Performance counters for an entire APL system function 201 class FunctionStatistics : public Statistics 202 { 203 public: 204 /// constructor: FunctionStatistics with ID \b id FunctionStatistics(Pfstat_ID id)205 FunctionStatistics(Pfstat_ID id) 206 : Statistics(id) 207 { reset(); } 208 209 /// overloaded Statistics::print() reset()210 virtual void reset() 211 { 212 vec_cycles.reset(); 213 vec_lengths.reset(); 214 } 215 216 /// overloaded Statistics::print() 217 virtual void print(ostream & out); 218 219 /// overloaded Statistics::save_data() 220 virtual void save_data(ostream & outf, const char * perf_name); 221 222 /// return the (CPU-)cycles statistics get_record() const223 virtual const Statistics_record * get_record() const 224 { return &vec_cycles; } 225 226 /// return the (CPU-)cycles statistics get_data() const227 const Statistics_record & get_data() const 228 { return vec_cycles; } 229 230 /// add a sample add_sample(uint64_t cycles,uint64_t veclen)231 void add_sample(uint64_t cycles, uint64_t veclen) 232 { 233 vec_cycles.add_sample(cycles); 234 vec_lengths.add_sample(veclen); 235 } 236 237 protected: 238 /// a statistics of vector lengths 239 Statistics_record vec_lengths; 240 241 /// the cycles executed 242 Statistics_record vec_cycles; 243 }; 244 //----------------------------------------------------------------------------- 245 /// Performance counters for one cell level function 246 class CellFunctionStatistics : public Statistics 247 { 248 public: 249 /// constructor: reset this statistics CellFunctionStatistics(Pfstat_ID _id)250 CellFunctionStatistics(Pfstat_ID _id) 251 : Statistics(_id) 252 { reset(); } 253 254 /// reset this statistics: clear \b first and \b subsequent records reset()255 virtual void reset() 256 { 257 first.reset(); 258 subsequent.reset(); 259 } 260 261 /// add a sample to \b this statistics add_sample(uint64_t val,bool subseq)262 void add_sample(uint64_t val, bool subseq) 263 { 264 if (subseq) subsequent.add_sample(val); 265 else first.add_sample(val); 266 } 267 268 /// overloaded Statistics::print() 269 virtual void print(ostream & out); 270 271 /// overloaded Statistics::save_data() 272 virtual void save_data(ostream & outf, const char * perf_name); 273 274 /// return the record for the first executions get_first_record() const275 virtual const Statistics_record * get_first_record() const 276 { return &first; } 277 278 /// return the record for subsequent executions get_record() const279 virtual const Statistics_record * get_record() const 280 { return &subsequent; } 281 282 /// return the cycles sum get_sum() const283 uint64_t get_sum() const 284 { return first.get_sum() + subsequent.get_sum(); } 285 286 /// return the square of cycles sums get_sum2() const287 double get_sum2() const 288 { return first.get_sum2() + subsequent.get_sum2(); } 289 290 /// return the number of first executions get_count1() const291 uint64_t get_count1() const 292 { return first.get_count(); } 293 294 /// return the number of subsequent executions get_countN() const295 uint64_t get_countN() const 296 { return subsequent.get_count(); } 297 298 /// return the number of all executions get_count() const299 uint64_t get_count() const 300 { return first.get_count() + subsequent.get_count(); } 301 302 protected: 303 /// statistics for first executions 304 Statistics_record first; 305 306 /// statistics for subsequent executions 307 Statistics_record subsequent; 308 }; 309 //============================================================================= 310 /** 311 Performance (cycle-) counters at different levels 312 **/ 313 /// A class containing performance counters for several functions 314 class Performance 315 { 316 public: 317 318 /// return statistics object for ID \b id 319 static Statistics * get_statistics(Pfstat_ID id); 320 321 /// return statistics type of ID \b id 322 static int get_statistics_type(Pfstat_ID id); 323 324 /// print all counters 325 static void print(Pfstat_ID which, ostream & out); 326 327 /// write all counters to .def file 328 static void save_data(ostream & out, ostream & out_file); 329 330 /// reset all counters 331 static void reset_all(); 332 333 #define perfo_1(id, ab, name, thr) \ 334 /** monadic cell function statistics **/ \ 335 static CellFunctionStatistics cfs_ ## id ## ab; \ 336 /** monadic parallel executionthreshold **/ \ 337 static const ShapeItem thresh_ ## id ## ab = thr; 338 339 #define perfo_2(id, ab, name, thr) \ 340 /** dyadic cell function statistics **/ \ 341 static CellFunctionStatistics cfs_ ## id ## ab; \ 342 /** dyadic parallel executionthreshold **/ \ 343 static const ShapeItem thresh_ ## id ## ab = thr; 344 345 #define perfo_3(id, ab, name, thr) \ 346 /** function statistics **/ \ 347 static FunctionStatistics fs_ ## id ## ab; 348 349 #define perfo_4(id, ab, name, thr) \ 350 /** function statistics **/ \ 351 static FunctionStatistics fs_ ## id ## ab; 352 353 #include "Performance.def" 354 }; 355 356 #endif // __PERFORMANCE_HH_DEFINED__ 357