1 #pragma once 2 3 /* for measurement of CPU cycles .. 4 * 5 * requires 6 * sudo apt-get install libpapi-dev papi-tools 7 * on debian/ubuntu linux distributions 8 * 9 */ 10 11 #ifdef HAVE_PAPI 12 #include <papi.h> 13 #endif 14 15 #include <stdio.h> 16 17 18 struct papi_perf_counter 19 { papi_perf_counterpapi_perf_counter20 papi_perf_counter() 21 : realTime(0.0F), processTime(0.0F), instructions(0LL), ipc(0.0F) 22 , started(false), finished(false), print_at_destruction(false) 23 { } 24 25 papi_perf_counter(int _start, bool print_at_destruction_ = true) print_at_destructionpapi_perf_counter26 : print_at_destruction(print_at_destruction_) 27 { 28 (void)_start; 29 start(); 30 } 31 ~papi_perf_counterpapi_perf_counter32 ~papi_perf_counter() 33 { 34 if (print_at_destruction) 35 print(stderr); 36 } 37 startpapi_perf_counter38 bool start() 39 { 40 static bool reported_start_error = false; 41 #ifdef HAVE_PAPI 42 int ret = PAPI_ipc(&realTime, &processTime, &instructions, &ipc); 43 if (ret && !reported_start_error) 44 { 45 reported_start_error = true; 46 fprintf(stderr, "papi_perf_counter::start(): PAPI_ipc() returned error %d\n", ret); 47 } 48 #else 49 if (!reported_start_error) 50 { 51 reported_start_error = true; 52 fprintf(stderr, "papi_perf_counter::start(): no HAVE_PAPI\n"); 53 } 54 int ret = 1; 55 #endif 56 started = (!ret); 57 finished = false; 58 return started; 59 } 60 finishpapi_perf_counter61 bool finish() 62 { 63 papi_perf_counter end(1, false); 64 if (started && !finished && end.started) 65 { 66 realTime = end.realTime - realTime; 67 processTime = end.processTime - processTime; 68 instructions = end.instructions - instructions; 69 ipc = end.ipc; 70 finished = true; 71 return true; 72 } 73 return false; 74 } 75 76 void print(FILE *f = stdout) 77 { 78 if (started && !finished) 79 finish(); 80 if (!started || !finished) 81 return; 82 double cycles = instructions / ipc; 83 fprintf(f, "real %g, process %g, instructions %lld, ins/cycle %f => cycles %g\n" 84 , realTime, processTime, instructions, ipc, cycles 85 ); 86 started = false; 87 } 88 89 float realTime; 90 float processTime; 91 long long instructions; 92 float ipc; 93 bool started; 94 bool finished; 95 bool print_at_destruction; 96 }; 97 98