diff --git a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/fwd.h b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/fwd.h index 99ac53aaf6..bc2009ae6a 100644 --- a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/fwd.h +++ b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/fwd.h @@ -78,6 +78,7 @@ typedef enum // NOLINT(performance-enum-size) ///< with current version of rocprofiler ROCPROFILER_STATUS_ERROR_INVALID_ARGUMENT, ///< Function invoked with one or more invalid ///< arguments + ROCPROFILER_STATUS_ERROR_METRIC_NOT_VALID_FOR_AGENT, ///< Invalid metric supplied to agent. ROCPROFILER_STATUS_LAST, } rocprofiler_status_t; diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.cpp index df64c66465..a0c83751c9 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.cpp @@ -231,6 +231,30 @@ getMetricsForAgent(const std::string& agent) return empty; } +bool +checkValidMetric(const std::string& agent, const Metric& metric) +{ + static auto*& agent_to_id = + common::static_object>>:: + construct([]() -> std::unordered_map> { + std::unordered_map> ret; + const auto& map = *CHECK_NOTNULL(getMetricMap()); + for(const auto& [agent_name, metrics] : map) + { + auto& id_set = + ret.emplace(agent_name, std::unordered_set{}).first->second; + for(const auto& m : metrics) + { + id_set.insert(m.id()); + } + } + return ret; + }()); + + const auto* agent_map = common::get_val(*agent_to_id, agent); + return agent_map != nullptr && agent_map->count(metric.id()) > 0; +} + bool operator<(Metric const& lhs, Metric const& rhs) { diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.hpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.hpp index 75cb308c1c..e0ac0b82b8 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.hpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/metrics.hpp @@ -115,6 +115,12 @@ getMetricsForAgent(const std::string&); */ const MetricIdMap* getMetricIdMap(); + +/** + * Checks if a metric is valid for a given agent + **/ +bool +checkValidMetric(const std::string& agent, const Metric& metric); } // namespace counters } // namespace rocprofiler diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/tests/metrics_test.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/tests/metrics_test.cpp index 8cabd90520..5b0238680b 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/tests/metrics_test.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/counters/tests/metrics_test.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include "lib/rocprofiler-sdk/agent.hpp" #include "lib/rocprofiler-sdk/counters/metrics.hpp" @@ -121,3 +123,55 @@ TEST(metrics, derived_load) EXPECT_TRUE(equal(itr, *val)) << fmt::format("\n\t{} \n\t\t!= \n\t{}", itr, *val); } } + +TEST(metrics, check_agent_valid) +{ + const auto& rocp_data = *counters::getMetricMap(); + auto common_metrics = [&]() -> std::set { + std::set ret; + for(const auto& [gfx, counters] : rocp_data) + { + std::set counter_ids; + for(const auto& metric : counters) + { + counter_ids.insert(metric.id()); + } + + if(ret.empty()) + { + ret = counter_ids; + } + else + { + std::set out_intersection; + std::set_intersection(ret.begin(), + ret.end(), + counter_ids.begin(), + counter_ids.end(), + std::inserter(out_intersection, out_intersection.begin())); + } + + if(ret.empty()) return ret; + } + return ret; + }(); + + for(const auto& [gfx, counters] : rocp_data) + { + for(const auto& metric : counters) + { + ASSERT_EQ(counters::checkValidMetric(gfx, metric), true) + << gfx << " " << fmt::format("{}", metric); + } + + for(const auto& [other_gfx, other_counters] : rocp_data) + { + if(other_gfx == gfx) continue; + for(const auto& metric : other_counters) + { + if(common_metrics.count(metric.id())) continue; + EXPECT_EQ(counters::checkValidMetric(gfx, metric), false); + } + } + } +} diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/profile_config.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/profile_config.cpp index 4545f9e9c3..3d253e0f96 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/profile_config.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/profile_config.cpp @@ -51,13 +51,16 @@ rocprofiler_create_profile_config(rocprofiler_agent_t agent, std::make_shared(); const auto& id_map = *CHECK_NOTNULL(rocprofiler::counters::getMetricIdMap()); - for(size_t i = 0; i < counters_count; i++) { auto& counter_id = counters_list[i]; const auto* metric_ptr = rocprofiler::common::get_val(id_map, counter_id.handle); if(!metric_ptr) return ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND; + if(!rocprofiler::counters::checkValidMetric(std::string(agent.name), *metric_ptr)) + { + return ROCPROFILER_STATUS_ERROR_METRIC_NOT_VALID_FOR_AGENT; + } config->metrics.push_back(*metric_ptr); } diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/rocprofiler.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/rocprofiler.cpp index c6c7abe308..4fffaa7dd2 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/rocprofiler.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/rocprofiler.cpp @@ -71,6 +71,8 @@ ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_INCOMPATIBLE_ABI, "with this version of rocprofiler") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_INVALID_ARGUMENT, "Function invoked with one or more invalid arguments") +ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_METRIC_NOT_VALID_FOR_AGENT, + "Metric is not valid for the agent") template const char*