Skip to content

Commit

Permalink
feat(metrics): Implement heterogenous architecture support
Browse files Browse the repository at this point in the history
With Alder Lake, the Linux kernel gained an architecture, where
different cores can have different sets of events available.

This commit makes lo2s respect the
/sys/bus/event_source/devices/[pmu]/cpus file, which specifies which
CPUs support that PMU and subsequently only opens the events on the CPUs
that support it.
  • Loading branch information
cvonelm committed Oct 7, 2022
1 parent a996db5 commit af5596a
Show file tree
Hide file tree
Showing 34 changed files with 717 additions and 528 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ set(SOURCE_FILES

src/perf/event_provider.cpp

src/perf/counter/counter_collection.cpp
src/perf/counter/counter_provider.cpp
src/perf/counter/group/reader.cpp
src/perf/counter/userspace/reader.cpp

Expand Down
5 changes: 0 additions & 5 deletions include/lo2s/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ struct Config
bool quiet;
// Optional features
std::vector<std::string> tracepoint_events;
std::vector<std::string> perf_group_events;
std::vector<std::string> perf_userspace_events;
#ifdef HAVE_X86_ADAPT
std::vector<std::string> x86_adapt_knobs;
#endif
Expand Down Expand Up @@ -83,9 +81,6 @@ struct Config
std::uint64_t metric_count;
std::uint64_t metric_frequency;

std::string metric_leader;
bool standard_metrics;

// time synchronization
bool use_clockid;
bool use_pebs;
Expand Down
4 changes: 2 additions & 2 deletions include/lo2s/monitor/cpu_set_monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#pragma once

#include <lo2s/monitor/main_monitor.hpp>

#include <lo2s/monitor/scope_monitor.hpp>
#include <lo2s/types.hpp>

#include <vector>

Expand All @@ -44,7 +44,7 @@ class CpuSetMonitor : public MainMonitor
void run();

private:
std::map<int, ScopeMonitor> monitors_;
std::map<Cpu, ScopeMonitor> monitors_;
};
} // namespace monitor
} // namespace lo2s
21 changes: 17 additions & 4 deletions include/lo2s/perf/counter/counter_collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ struct CounterCollection
{
EventDescription leader;
std::vector<EventDescription> counters;

double get_scale(int index) const
{
if (index == 0)
Expand All @@ -47,10 +46,24 @@ struct CounterCollection
return counters[index - 1].scale;
}
}
};
friend bool operator==(const CounterCollection& lhs, const CounterCollection& rhs)
{
if (lhs.leader == rhs.leader)
{
return lhs.counters == rhs.counters;
}
return false;
}

const CounterCollection& requested_userspace_counters();
const CounterCollection& requested_group_counters();
friend bool operator<(const CounterCollection& lhs, const CounterCollection& rhs)
{
if (lhs.leader == rhs.leader)
{
return lhs.counters < rhs.counters;
}
return lhs.leader < rhs.leader;
}
};

} // namespace counter
} // namespace perf
Expand Down
65 changes: 65 additions & 0 deletions include/lo2s/perf/counter/counter_provider.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* This file is part of the lo2s software.
* Linux OTF2 sampling
*
* Copyright (c) 2017,
* Technische Universitaet Dresden, Germany
*
* lo2s is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* lo2s is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with lo2s. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <lo2s/measurement_scope.hpp>
#include <lo2s/perf/counter/counter_collection.hpp>
#include <lo2s/perf/event_description.hpp>

#include <vector>

namespace lo2s
{
namespace perf
{
namespace counter
{
class CounterProvider
{
public:
CounterProvider()
{
}

static CounterProvider& instance()
{
static CounterProvider provider;
return provider;
}

void initialize_group_counters(const std::string& leader,
const std::vector<std::string>& counters);
void initialize_userspace_counters(const std::vector<std::string>& counters);

bool has_group_counters(ExecutionScope scope);
bool has_userspace_counters(ExecutionScope scope);

CounterCollection collection_for(MeasurementScope scope);

private:
EventDescription group_leader_;
std::vector<EventDescription> group_events_;
std::vector<EventDescription> userspace_events_;
};
} // namespace counter
} // namespace perf
} // namespace lo2s
2 changes: 2 additions & 0 deletions include/lo2s/perf/counter/group/reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <lo2s/perf/counter/counter_collection.hpp>
#include <lo2s/perf/counter/group/group_counter_buffer.hpp>
#include <lo2s/perf/event_reader.hpp>

#include <vector>

extern "C"
Expand Down Expand Up @@ -72,6 +73,7 @@ class Reader : public EventReader<T>
protected:
int group_leader_fd_;
std::vector<int> counter_fds_;
CounterCollection counter_collection_;
GroupCounterBuffer counter_buffer_;
};
} // namespace group
Expand Down
3 changes: 0 additions & 3 deletions include/lo2s/perf/counter/group/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ class Writer : public Reader<Writer>, MetricWriter

using Reader<Writer>::handle;
bool handle(const RecordSampleType* sample);

private:
const CounterCollection& counters_;
};
} // namespace group
} // namespace counter
Expand Down
2 changes: 2 additions & 0 deletions include/lo2s/perf/counter/userspace/reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#pragma once

#include <lo2s/execution_scope.hpp>
#include <lo2s/perf/counter/counter_collection.hpp>
#include <lo2s/perf/counter/userspace/userspace_counter_buffer.hpp>
#include <lo2s/trace/trace.hpp>

Expand Down Expand Up @@ -54,6 +55,7 @@ class Reader

protected:
std::vector<int> counter_fds_;
CounterCollection counter_collection_;
UserspaceCounterBuffer counter_buffer_;
int timer_fd_;

Expand Down
3 changes: 0 additions & 3 deletions include/lo2s/perf/counter/userspace/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ class Writer : public Reader<Writer>, MetricWriter
Writer(ExecutionScope scope, trace::Trace& trace);

bool handle(std::vector<UserspaceReadFormat>& data);

private:
const CounterCollection& counters_;
};
} // namespace userspace
} // namespace counter
Expand Down
46 changes: 44 additions & 2 deletions include/lo2s/perf/event_description.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@

#pragma once

#include <lo2s/execution_scope.hpp>
#include <lo2s/topology.hpp>

#include <set>
#include <string>

extern "C"
Expand All @@ -43,9 +47,11 @@ enum class Availability
struct EventDescription
{
EventDescription(const std::string& name, perf_type_id type, std::uint64_t config,
std::uint64_t config1 = 0, double scale = 1, std::string unit = "#")
std::uint64_t config1 = 0, std::set<Cpu> cpus = std::set<Cpu>(),
double scale = 1, std::string unit = "#",
Availability availability = Availability::UNAVAILABLE)
: name(name), type(type), config(config), config1(config1), scale(scale), unit(unit),
availability(Availability::UNAVAILABLE)
availability(availability), cpus_(cpus)
{
}

Expand All @@ -55,13 +61,49 @@ struct EventDescription
{
}

const std::set<Cpu>& supported_cpus() const
{
if (cpus_.empty())
{
return Topology::instance().cpus();
}
return cpus_;
}

bool is_supported_in(ExecutionScope scope) const
{
// per-process should always work. the counter will just not count if the process is
// scheduled on a core that is not supprted by that counter
return scope.is_thread() || cpus_.empty() || cpus_.count(scope.as_cpu());
}

friend bool operator==(const EventDescription& lhs, const EventDescription& rhs)
{
return (lhs.type == rhs.type) && (lhs.config == rhs.config) && (lhs.config1 == rhs.config1);
}

friend bool operator<(const EventDescription& lhs, const EventDescription& rhs)
{
if (lhs.type == rhs.type)
{
if (lhs.config == rhs.config)
{
return lhs.config1 < rhs.config1;
}
return lhs.config < rhs.config;
}
return lhs.type < rhs.type;
}
std::string name;
perf_type_id type;
std::uint64_t config;
std::uint64_t config1;
double scale;
std::string unit;
Availability availability;

private:
std::set<Cpu> cpus_;
};
} // namespace perf
} // namespace lo2s
2 changes: 1 addition & 1 deletion include/lo2s/perf/event_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class EventProvider
static std::vector<EventDescription> get_predefined_events();
static std::vector<EventDescription> get_pmu_events();

static const EventDescription& get_default_metric_leader_event();
static const EventDescription& fallback_metric_leader_event();

class InvalidEvent : public std::runtime_error
{
Expand Down
Loading

0 comments on commit af5596a

Please sign in to comment.