-
Notifications
You must be signed in to change notification settings - Fork 2
/
PapiInstance.cpp
137 lines (114 loc) · 3.57 KB
/
PapiInstance.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "PapiInstance.h"
#include <algorithm>
#ifdef _LIB_MONITOR_
void *monitor_init_process(int *argc, char **argv, void *data) {
PapiW_start();
return NULL;
}
void monitor_fini_process(int how, void *data) { PapiW_stopAndPrint(); }
#endif
void PapiW_start() {
printf("Starting Papi Measurement\n");
PapiInstance *instance = papi.create();
instance->addEvent(PAPI_TOT_INS);
instance->addEvent(PAPI_L1_ICM);
instance->start();
}
void PapiW_stopAndPrint() {
PapiInstance *instance = papi.create();
instance->stop();
std::cout << "\nThe measured total instructions were: "
<< instance->getEventValue(PAPI_TOT_INS) << "\n";
std::cout << "Collected L1_ICM Events: "
<< instance->getEventValue(PAPI_L1_ICM) << std::endl;
}
PapiInstance *Papi::create() {
if (instance == nullptr) {
instance.reset(new PapiInstance());
}
return instance.get();
}
std::string getPAPIError(int err) {
char *errstr = PAPI_strerror(err);
std::string str;
if (errstr) {
str = std::string(errstr);
}
return str;
}
PapiInstance::PapiInstance() : eventSet(PAPI_NULL) {
int returnVal = PAPI_library_init(PAPI_VER_CURRENT);
if ((returnVal != PAPI_VER_CURRENT && returnVal > 0) || returnVal < 0) {
throw std::string("The Papi initialization failed");
}
if (PAPI_create_eventset(&eventSet) != PAPI_OK) {
throw std::string("Creation of event set failed.");
}
}
PapiInstance::~PapiInstance() {
std::vector<long long> vals(eventValMap.size());
if (PAPI_stop(eventSet, vals.data()) != PAPI_OK) {
// TODO Do some error handling here
}
assert(vals.size() == eventRegChain.size() && "As many results as events");
mapValuesToMapEntries(vals);
}
void PapiInstance::addEvent(int event) {
if (PAPI_add_event(eventSet, event) != PAPI_OK) {
throw std::string("Adding the event failed.");
}
eventValMap[event] = 0;
eventRegChain.push_back(event);
}
void PapiInstance::start() {
int state;
int err = PAPI_state(eventSet, &state);
if (err != PAPI_OK) {
throw std::string("EventSet state check failed with " + getPAPIError(err));
}
if (state == PAPI_RUNNING) {
return;
}
PAPI_start(eventSet);
if (err != PAPI_OK) {
throw std::string("Could not start measurement (" + getPAPIError(err) +
"): " + std::to_string(err));
}
}
void PapiInstance::stop() {
std::vector<long long> vals(eventValMap.size());
int err = PAPI_stop(eventSet, vals.data());
if (err != PAPI_OK) {
throw std::string("There went something wrong when trying to stop PAPI " +
getPAPIError(err));
}
assert(vals.size() == eventRegChain.size() && "As many results as events");
mapValuesToMapEntries(vals);
}
void PapiInstance::reset() {
for (auto &p : eventValMap) {
p.second = 0;
}
std::for_each(eventRegChain.begin(), eventRegChain.end(),
[](int &ec) { PAPI_reset(ec); });
}
void PapiInstance::read() {
std::vector<long long> vals(eventValMap.size());
if (PAPI_read(eventSet, vals.data()) != PAPI_OK) {
throw std::string("Could not read cunters");
}
assert(vals.size() == eventRegChain.size() && "As many results as events");
mapValuesToMapEntries(vals);
}
void PapiInstance::mapValuesToMapEntries(const std::vector<long long> &vals) {
for (int i = 0; i < vals.size(); ++i) {
eventValMap[eventRegChain.at(i)] = vals.at(i);
}
}
long long PapiInstance::getEventValue(int event) {
if (eventValMap.find(event) == eventValMap.end()) {
throw std::string("The requested counter value was not found.");
}
return eventValMap[event];
}
Papi::Papi() : instance(nullptr) {}