00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_PAPI_INCLUDE
00013 #define MTL_PAPI_INCLUDE
00014
00015 #ifdef MTL_HAS_PAPI
00016
00017 #include <papi.h>
00018 #include <boost/numeric/mtl/utility/exception.hpp>
00019
00020 #endif // MTL_HAS_PAPI
00021
00022 namespace mtl { namespace utility {
00023
00025 struct papi_error : public runtime_error
00026 {
00027 explicit papi_error(const char *s= "PAPI error") : runtime_error(s) {}
00028 };
00029
00030 struct papi_version_mismatch : public papi_error
00031 {
00032 explicit papi_version_mismatch(const char *s= "PAPI: version mismatch") : papi_error(s) {}
00033 };
00034
00035 struct papi_no_counters : public papi_error
00036 {
00037 explicit papi_no_counters(const char *s= "PAPI: no counters") : papi_error(s) {}
00038 };
00039
00040 struct papi_create_eventset_error : public papi_error
00041 {
00042 explicit papi_create_eventset_error(const char *s= "PAPI: create event set error") : papi_error(s) {}
00043 };
00044
00045 struct papi_name_to_code_error : public papi_error
00046 {
00047 explicit papi_name_to_code_error(const char *s= "PAPI: name to code error") : papi_error(s) {}
00048 };
00049
00050 struct papi_query_event_error : public papi_error
00051 {
00052 explicit papi_query_event_error(const char *s= "PAPI: query event error") : papi_error(s) {}
00053 };
00054
00055 struct papi_start_event_error : public papi_error
00056 {
00057 explicit papi_start_event_error(const char *s= "PAPI: start event error") : papi_error(s) {}
00058 };
00059
00060 struct papi_add_event_error : public papi_error
00061 {
00062 explicit papi_add_event_error(const char *s= "PAPI: add event error") : papi_error(s) {}
00063 };
00064
00065 struct papi_reset_error : public papi_error
00066 {
00067 explicit papi_reset_error(const char *s= "PAPI: reset error") : papi_error(s) {}
00068 };
00069
00070 struct papi_read_error : public papi_error
00071 {
00072 explicit papi_read_error(const char *s= "PAPI: read error") : papi_error(s) {}
00073 };
00074
00075 struct papi_index_range_error : public papi_error
00076 {
00077 explicit papi_index_range_error(const char *s= "PAPI: index range error") : papi_error(s) {}
00078 };
00079
00080
00081 #ifdef MTL_HAS_PAPI
00082
00083 class papi_t
00084 {
00085 void init_papi()
00086 {
00087 static bool initialized= false;
00088 if (!initialized) {
00089
00090 MTL_THROW_IF(PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT,
00091 papi_version_mismatch());
00092
00093 num_counters = PAPI_get_opt(PAPI_MAX_HWCTRS, NULL);
00094 MTL_THROW_IF(num_counters <= 0, papi_no_counters());
00095
00096 counters= new long_long[num_counters];
00097
00098 MTL_THROW_IF(PAPI_create_eventset(&event_set) != PAPI_OK, papi_create_eventset_error());
00099 initialized= true;
00100 }
00101 }
00102
00103 public:
00104 const static bool true_papi = true;
00105
00106 papi_t() : event_set(PAPI_NULL), active_events(0)
00107 {
00108 init_papi();
00109 }
00110
00111
00112 ~papi_t()
00113 {
00114 delete[](counters);
00115 }
00116
00117
00118
00119 int add_event(const char* name)
00120 {
00121 int code;
00122 MTL_THROW_IF(PAPI_event_name_to_code(const_cast<char*>(name), &code) != PAPI_OK,
00123 papi_name_to_code_error());
00124
00125 MTL_THROW_IF (PAPI_query_event(code) != PAPI_OK,
00126 papi_query_event_error());
00127 MTL_THROW_IF (PAPI_add_event(event_set, code) != PAPI_OK,
00128 papi_add_event_error());
00129 list_events();
00130 return active_events++;
00131 }
00132
00133 void start()
00134 {
00135 MTL_THROW_IF (PAPI_start(event_set) != PAPI_OK,
00136 papi_start_event_error());
00137 reset();
00138 }
00139
00140 void list_events()
00141 {
00142 #if 0
00143 int evv[8], num= 8;
00144 PAPI_list_events(event_set, evv, &num);
00145 for (int i= 0; i < num; i++ ) std::cout << evv[i] << "\n";
00146 #endif
00147 }
00148
00149 bool is_event_supported(const char* name) const
00150 {
00151 int code;
00152 return PAPI_event_name_to_code(const_cast<char*>(name), &code) == PAPI_OK
00153 && PAPI_query_event(code) == PAPI_OK;
00154 }
00155
00156 void reset()
00157 {
00158 MTL_THROW_IF(PAPI_reset(event_set) != PAPI_OK, papi_reset_error());
00159 }
00160
00161 void read()
00162 {
00163 list_events();
00164 MTL_THROW_IF (PAPI_read(event_set, counters) != PAPI_OK, papi_read_error());
00165
00166 }
00167
00168 long_long operator[](int index) const
00169 {
00170 if (index < 0 || index >= active_events) throw papi_index_range_error();
00171 return counters[index];
00172 }
00173
00174
00175 int num_counters, event_set, active_events;
00176 long_long *counters;
00177 };
00178
00179 #else // no papi
00180
00181
00182
00183 struct papi_t
00184 {
00185 const static bool true_papi = false;
00186 int add_event(const char* name) { return 0;}
00187 void start() {}
00188 bool is_event_supported(const char* name) const { return false;}
00189 void reset() {}
00190 void read() {}
00191 long long operator[](int index) const { return 0; }
00192 };
00193
00194 #endif
00195
00196 }}
00197
00198
00199 #endif // MTL_PAPI_INCLUDE