Merge pull request #20 from ARM-software/fix-pmu-counters
Resetting and sampling PMU counters at a high frequency seems to yield incorrect result.
This PR adds differential readings which yield more reliable results.
diff --git a/vendor/arm/pmu/pmu_counter.cpp b/vendor/arm/pmu/pmu_counter.cpp
index b82aa5a..a7b1f2c 100644
--- a/vendor/arm/pmu/pmu_counter.cpp
+++ b/vendor/arm/pmu/pmu_counter.cpp
@@ -90,6 +90,12 @@
bool PmuCounter::reset()
{
const int result = ioctl(_fd, PERF_EVENT_IOC_RESET, 0);
+
+ if (result == -1)
+ {
+ throw std::runtime_error("Failed to reset PMU counter: " + std::string(std::strerror(errno)));
+ }
+
return result != -1;
}
diff --git a/vendor/arm/pmu/pmu_counter.h b/vendor/arm/pmu/pmu_counter.h
index a1bbdfc..183dcda 100644
--- a/vendor/arm/pmu/pmu_counter.h
+++ b/vendor/arm/pmu/pmu_counter.h
@@ -49,7 +49,7 @@
*
* @param[in] config Counter identifier.
*/
- explicit PmuCounter(uint64_t config);
+ PmuCounter(uint64_t config);
/** Default destructor. */
~PmuCounter();
diff --git a/vendor/arm/pmu/pmu_profiler.cpp b/vendor/arm/pmu/pmu_profiler.cpp
index 52b49cf..d6af31b 100644
--- a/vendor/arm/pmu/pmu_profiler.cpp
+++ b/vendor/arm/pmu/pmu_profiler.cpp
@@ -49,11 +49,11 @@
try
{
// Create a PMU counter with the specified configuration
- auto pmu_counter_res = pmu_counters_.emplace(counter, PmuCounter{pmu_config->second});
+ auto pmu_counter_res = pmu_counters_.emplace(counter, pmu_config->second);
// Try reading a value from the counter to check that it opened correctly
auto &pmu_counter = pmu_counter_res.first->second;
- pmu_counter.get_value<double>();
+ pmu_counter.get_value<long long>();
// PMU counter is created and can retrieve values
available_counters_.insert(counter);
@@ -77,6 +77,7 @@
for (auto &pmu_counter : pmu_counters_)
{
pmu_counter.second.reset();
+ prev_measurements_[pmu_counter.first] = Value{};
}
}
@@ -92,8 +93,12 @@
try
{
- measurements_[pmu_counter->first] = pmu_counter->second.get_value<long long>();
- pmu_counter->second.reset();
+ auto value = pmu_counter->second.get_value<long long>();
+
+ // Resetting the PMU counter every frame seems to alter the data,
+ // so we make a differential reading.
+ measurements_[pmu_counter->first] = value - prev_measurements_[pmu_counter->first].get<long long>();
+ prev_measurements_[pmu_counter->first] = value;
}
catch (const std::runtime_error &e)
{
diff --git a/vendor/arm/pmu/pmu_profiler.h b/vendor/arm/pmu/pmu_profiler.h
index 14fdc89..3a003e2 100644
--- a/vendor/arm/pmu/pmu_profiler.h
+++ b/vendor/arm/pmu/pmu_profiler.h
@@ -70,6 +70,7 @@
bool running_{false};
CpuMeasurements measurements_{};
+ CpuMeasurements prev_measurements_{};
std::unordered_map<CpuCounter, PmuCounter, CpuCounterHash> pmu_counters_{};
};