-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathevents-intel.hpp
More file actions
172 lines (128 loc) · 4.22 KB
/
events-intel.hpp
File metadata and controls
172 lines (128 loc) · 4.22 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#pragma once
#include <chrono>
#include <iostream>
#include <vector>
#include "intel-pcm/cpucounters.h"
#include "stats.hpp"
#include "throw-with-trace.hpp"
// Prototipes
struct EventSelectRegister;
struct CoreEvent;
void pcm_build_event(const char *event_str, EventSelectRegister ®, CoreEvent &event);
void pcm_cleanup();
void pcm_reset();
// Structures
struct CoreEvent
{
char name[256];
uint64_t value;
uint64_t msr_value;
char *description;
};
template <typename Resume, typename Wait, typename Pause>
class PerfCountMon
{
PCM *m = nullptr;
// Callable template attributes
Resume resume;
Wait wait;
Pause pause;
std::vector<std::string> event_names;
public:
PerfCountMon() = delete;
PerfCountMon(Resume r, Wait w, Pause p) : m(PCM::getInstance()), resume(r), wait(w), pause(p) {}
void clean()
{
m->cleanup();
}
void reset()
{
m->resetPMU();
}
void check_status(PCM::ErrorCode status)
{
switch (status)
{
case PCM::Success:
break;
case PCM::MSRAccessDenied:
throw_with_trace(std::runtime_error("Access to PMU denied: No MSR or PCI CFG space access"));
case PCM::PMUBusy:
throw_with_trace(std::runtime_error("Access to PMU denied: The Performance Monitoring Unit is occupied by another application"));
default:
throw_with_trace(std::runtime_error("Access to PMU denied: unknown error)"));
}
}
void mon_custom_events(const std::vector<std::string> &str_events)
{
CoreEvent events[MAX_EVENTS];
EventSelectRegister regs[MAX_EVENTS];
PCM::ExtendedCustomCoreEventDescription conf;
if (str_events.size() > MAX_EVENTS)
throw_with_trace(std::runtime_error("At most " + std::to_string(MAX_EVENTS) + " events are allowed"));
// Build events
for (size_t i = 0; i < str_events.size(); i++)
{
pcm_build_event(str_events[i].c_str(), regs[i], events[i]);
event_names.push_back(events[i].name);
}
// Prepare conf
conf.fixedCfg = NULL; // default
conf.nGPCounters = 4;
conf.gpCounterCfg = regs;
conf.OffcoreResponseMsrValue[0] = events[0].msr_value;
conf.OffcoreResponseMsrValue[1] = events[1].msr_value;
// Program PCM unit
PCM::ErrorCode status = m->program(PCM::EXT_CUSTOM_CORE_EVENTS, &conf);
check_status(status);
}
// Takes snapshot, works, takes another snapshot, and returns the results
uint64_t measure(const std::vector<uint32_t> &cores, std::vector<Measurement> &results)
{
namespace chr = std::chrono;
auto sb = SystemCounterState();
auto sa = SystemCounterState();
auto cb = std::vector<CoreCounterState>(m->getNumCores());
auto ca = std::vector<CoreCounterState>(m->getNumCores());
auto skb = std::vector<SocketCounterState>(m->getNumSockets());
auto ska = std::vector<SocketCounterState>(m->getNumSockets());
results.clear();
// Resume applications
resume();
// Collect stats
auto start = chr::system_clock::now();
m->getCounterStates(cores, sb, skb, cb);
// Wait some time
wait();
// Collect stats
m->getCounterStates(cores, sa, ska, ca);
uint64_t duration = chr::duration_cast<chr::microseconds>
(chr::system_clock::now() - start).count();
// Pause applications
pause();
// Process stats
for (const auto &core : cores)
{
if (!m->isCoreOnline(core))
throw_with_trace(std::runtime_error("Core " + std::to_string(core) + " is not online"));
Measurement m =
{
.us = duration,
.instructions = getInstructionsRetired(cb[core], ca[core]),
.cycles = getCycles(cb[core], ca[core]),
.invariant_cycles = getInvariantTSC(cb[core], ca[core]),
.rel_freq = getRelativeFrequency(cb[core], ca[core]),
.act_rel_freq = getActiveRelativeFrequency(cb[core], ca[core]),
.l3_kbytes_occ = getL3CacheOccupancy(ca[core]),
.mc_gbytes_rd = getBytesReadFromMC(sb, sa) / double(1e9),
.mc_gbytes_wt = getBytesWrittenToMC(sb, sa) / double(1e9),
.proc_energy = getConsumedJoules(sb, sa), // Energy conumed by the processor, excluding the DRAM
.dram_energy = getDRAMConsumedJoules(sb, sa), // Energy consumed by the DRAM
};
for (size_t i = 0; i < event_names.size(); ++i)
m.events[event_names[i]] = getNumberOfCustomEvents(i, cb[core], ca[core]);
results.push_back(m);
}
return duration;
}
};