mirror of
https://github.com/google/benchmark.git
synced 2025-02-26 11:20:28 +08:00
Allow for collection of more PMUs than are physically available.
Normally we can only collect as many PMUs as we have physical PMU counters because they are managed as a single pinned group and extra requested PMUs will not be collected. With this patch we instead collect each PMU as a separate group once this limit is hit using PMU multiplexing.
This commit is contained in:
parent
ea71a14891
commit
2d609d4fa1
@ -86,6 +86,12 @@ PerfCounters PerfCounters::Create(
|
|||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initially try to create a single group which holds all PMUs since that
|
||||||
|
// has lower overhead. Group multiplexing doesn't work on all platforms so if
|
||||||
|
// that fails try again without using groups.
|
||||||
|
bool group_pmus = true;
|
||||||
|
retry_without_groups:
|
||||||
|
|
||||||
// Valid counters will populate these arrays but we start empty
|
// Valid counters will populate these arrays but we start empty
|
||||||
std::vector<std::string> valid_names;
|
std::vector<std::string> valid_names;
|
||||||
std::vector<int> counter_ids;
|
std::vector<int> counter_ids;
|
||||||
@ -96,11 +102,6 @@ PerfCounters PerfCounters::Create(
|
|||||||
counter_ids.reserve(counter_names.size());
|
counter_ids.reserve(counter_names.size());
|
||||||
|
|
||||||
const int kCounterMode = PFM_PLM3; // user mode only
|
const int kCounterMode = PFM_PLM3; // user mode only
|
||||||
|
|
||||||
// Group leads will be assigned on demand. The idea is that once we cannot
|
|
||||||
// create a counter descriptor, the reason is that this group has maxed out
|
|
||||||
// so we set the group_id again to -1 and retry - giving the algorithm a
|
|
||||||
// chance to create a new group leader to hold the next set of counters.
|
|
||||||
int group_id = -1;
|
int group_id = -1;
|
||||||
|
|
||||||
// Loop through all performance counters
|
// Loop through all performance counters
|
||||||
@ -150,7 +151,7 @@ PerfCounters PerfCounters::Create(
|
|||||||
// case.
|
// case.
|
||||||
attr.disabled = is_first;
|
attr.disabled = is_first;
|
||||||
attr.inherit = true;
|
attr.inherit = true;
|
||||||
attr.pinned = is_first;
|
attr.pinned = group_pmus;
|
||||||
attr.exclude_kernel = true;
|
attr.exclude_kernel = true;
|
||||||
attr.exclude_user = false;
|
attr.exclude_user = false;
|
||||||
attr.exclude_hv = true;
|
attr.exclude_hv = true;
|
||||||
@ -171,10 +172,14 @@ PerfCounters PerfCounters::Create(
|
|||||||
}
|
}
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
// If the file descriptor is negative we might have reached a limit
|
// If the file descriptor is negative we might have reached a limit
|
||||||
// in the current group. Set the group_id to -1 and retry
|
// in the current group. Let's try again without groups.
|
||||||
if (group_id >= 0) {
|
if (group_id >= 0 && group_pmus) {
|
||||||
// Create a new group
|
// Close all performance counters
|
||||||
group_id = -1;
|
for (int close_id : counter_ids) {
|
||||||
|
::close(close_id);
|
||||||
|
}
|
||||||
|
group_pmus = false;
|
||||||
|
goto retry_without_groups;
|
||||||
} else {
|
} else {
|
||||||
// At this point we have already retried to set a new group id and
|
// At this point we have already retried to set a new group id and
|
||||||
// failed. We then give up.
|
// failed. We then give up.
|
||||||
@ -197,8 +202,10 @@ PerfCounters PerfCounters::Create(
|
|||||||
if (group_id < 0) {
|
if (group_id < 0) {
|
||||||
// This is a leader, store and assign it to the current file descriptor
|
// This is a leader, store and assign it to the current file descriptor
|
||||||
leader_ids.push_back(id);
|
leader_ids.push_back(id);
|
||||||
|
if (group_pmus) {
|
||||||
group_id = id;
|
group_id = id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// This is a valid counter, add it to our descriptor's list
|
// This is a valid counter, add it to our descriptor's list
|
||||||
counter_ids.push_back(id);
|
counter_ids.push_back(id);
|
||||||
valid_names.push_back(name);
|
valid_names.push_back(name);
|
||||||
@ -214,9 +221,9 @@ PerfCounters PerfCounters::Create(
|
|||||||
// This should never happen but if it does, we give up on the
|
// This should never happen but if it does, we give up on the
|
||||||
// entire batch as recovery would be a mess.
|
// entire batch as recovery would be a mess.
|
||||||
GetErrorLogInstance() << "***WARNING*** Failed to start counters. "
|
GetErrorLogInstance() << "***WARNING*** Failed to start counters. "
|
||||||
"Claring out all counters.\n";
|
"Clearing out all counters.\n";
|
||||||
|
|
||||||
// Close all peformance counters
|
// Close all performance counters
|
||||||
for (int id : counter_ids) {
|
for (int id : counter_ids) {
|
||||||
::close(id);
|
::close(id);
|
||||||
}
|
}
|
||||||
@ -254,7 +261,7 @@ bool PerfCounters::IsCounterSupported(const std::string&) { return false; }
|
|||||||
PerfCounters PerfCounters::Create(
|
PerfCounters PerfCounters::Create(
|
||||||
const std::vector<std::string>& counter_names) {
|
const std::vector<std::string>& counter_names) {
|
||||||
if (!counter_names.empty()) {
|
if (!counter_names.empty()) {
|
||||||
GetErrorLogInstance() << "Performance counters not supported.\n";
|
GetErrorLogInstance() << "Performance counters not supported.";
|
||||||
}
|
}
|
||||||
return NoCounters();
|
return NoCounters();
|
||||||
}
|
}
|
||||||
@ -280,3 +287,4 @@ PerfCounters& PerfCounters::operator=(PerfCounters&& other) noexcept {
|
|||||||
}
|
}
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace benchmark
|
} // namespace benchmark
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ class BENCHMARK_EXPORT PerfCounterValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This reading is complex and as the goal of this class is to
|
// This reading is complex and as the goal of this class is to
|
||||||
// abstract away the intrincacies of the reading process, this is
|
// abstract away the intricacies of the reading process, this is
|
||||||
// a better place for it
|
// a better place for it
|
||||||
size_t Read(const std::vector<int>& leaders);
|
size_t Read(const std::vector<int>& leaders);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user