PFUNC
1.0
|
00001 #ifndef PFUNC_PERF_T_HPP 00002 #define PFUNC_PERF_T_HPP 00003 00004 #if PFUNC_USE_PAPI == 1 00005 00006 #include <pfunc/config.h> 00007 #include <papi.h> 00008 #include <pfunc/thread.hpp> 00009 #include <pfunc/environ.hpp> 00010 00011 namespace pfunc { 00026 struct virtual_perf_data { 00027 typedef long long event_value_type; 00028 00030 virtual ~virtual_perf_data () {} 00031 00033 virtual int get_num_events () const = 0; 00034 00036 virtual int* get_events () const = 0; 00037 00039 virtual event_value_type** get_event_storage () const = 0; 00040 }; 00041 00042 namespace detail { 00043 struct perf { 00044 static int* event_codes; 00045 static int num_events; 00046 00047 static bool initialize (const int* _event_codes, const int _num_events) { 00048 num_events = _num_events; 00049 event_codes = new int [num_events]; 00050 00051 /* Step 1: Copy the codes over */ 00052 for (int i=0; i<num_events; ++i) event_codes[i] = _event_codes[i]; 00053 00054 /* Step 2: Initialize the library */ 00055 int error; 00056 if (!PAPI_is_initialized ()) { 00057 if (PAPI_VER_CURRENT != (error = PAPI_library_init (PAPI_VER_CURRENT))) { 00058 printf ("PAPI_library_init failed: %d\n", error); 00059 return false; 00060 } 00061 } 00062 00063 /* Step 3: Initialize the threading support */ 00064 if (PAPI_OK != (error = PAPI_thread_init (pthread_self))) { 00065 printf ("PAPI_thread_init failed: %d\n", error); 00066 return false; 00067 } 00068 00069 /* Step 4: Check if we need to multiplex */ 00070 bool multiplex = false; 00071 if (num_events > PAPI_num_hwctrs ()) multiplex = true; 00072 00073 /* Step 5: Check if each of the events is supported */ 00074 for (int i=0; i<num_events; ++i) { 00075 if (PAPI_OK != (error = PAPI_query_event (event_codes[i]))) { 00076 char event_name [1024]; 00077 PAPI_event_code_to_name(event_codes[i], event_name); 00078 printf ("PAPI_query_event failed: %d (%s)\n", error, event_name); 00079 return false; 00080 } 00081 } 00082 00083 /* Step 6: We have reached till here -- so if multiplex was needed, start */ 00084 if (multiplex) { 00085 if (PAPI_OK != (error = PAPI_multiplex_init ())) { 00086 printf ("PAPI_multiplex_init failed: %d\n", error); 00087 return false; 00088 } 00089 } 00090 00091 return true; 00092 } 00093 00094 static void destroy () { delete [] event_codes; } 00095 00096 static int create_events () { 00097 ALIGN64 int event_set = PAPI_NULL; 00098 00099 /* Step 1: Create the event set */ 00100 if (PAPI_OK != PAPI_create_eventset (&event_set)) return -1; 00101 00102 /* Step 2: Check if this event needs to be multiplexed */ 00103 if (num_events > PAPI_num_hwctrs ()) 00104 if (PAPI_OK != PAPI_set_multiplex (event_set)) return -1; 00105 00106 /* Step 3: Add all the events to this event set */ 00107 for (int i=0; i<num_events; ++i) { 00108 char event_name [1024]; 00109 PAPI_event_code_to_name(event_codes[i], event_name); 00110 if (PAPI_OK != PAPI_add_event (event_set, event_codes [i])) { 00111 printf ("PAPI could not add %s\n", event_name); 00112 return -1; 00113 } 00114 } 00115 00116 return event_set; 00117 } 00118 00119 static bool start_events (const int& event_set) { 00120 return (PAPI_OK == PAPI_start (event_set)) ? true : false; 00121 } 00122 00123 static bool stop_events (const int& event_set, 00124 volatile long long int* event_values) { 00125 return (PAPI_OK == PAPI_stop (event_set, (long long*) event_values)) 00126 ? true : false; 00127 } 00128 00129 static int get_num_events (void) { return num_events; } 00130 00131 }; // struct perf 00132 00134 int perf::num_events = 0; 00135 int* perf::event_codes = NULL; 00136 00137 } /* namespace detail */ } /* namespace pfunc */ 00138 00139 #endif /* PFUNC_USE_PAPI */ 00140 00141 #endif // PFUNC_PERF_T_HPP