Convert counter def format to YAML (#976)

* Convert counter def format to YAML

Converts counter definition format to YAML with the
following structure:

```yaml
COUNTER_NAME:
 architectures:
  gfxXX: // Can be more than one, / deliminated if they share idential data
    block: <Optional>
    event: <Optional>
    expression: <optional>
    description: <Optional> // In case per arch notes are needed
  gfxYY:
    ...
 description: General counter desctiption
```

All counters (derived and hardware) are now defined
in the same file for ease of future additions/subtractions.

Removes existing XML parser. Keeps the existing XML
definitions for now (since other tools still rely on
its presence).
This commit is contained in:
Benjamin Welton
2024-07-12 16:20:33 -07:00
committed by GitHub
parent 2be3543c7b
commit 34897d318f
13 changed files with 4202 additions and 734 deletions
+72 -43
View File
@@ -27,11 +27,19 @@
#include "lib/common/filesystem.hpp"
#include "lib/common/static_object.hpp"
#include "lib/common/utility.hpp"
#include "lib/common/xml.hpp"
#include "lib/rocprofiler-sdk/agent.hpp"
#include "glog/logging.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/detail/impl.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/parse.h"
#include "yaml-cpp/parser.h"
#include <dlfcn.h> // for dladdr
#include <cstdint>
#include <cstdlib>
@@ -79,55 +87,76 @@ get_constants()
}
return constants;
}
// Future TODO: inheritance? does it work for derived_counters.xml?
/**
* Expected YAML Format:
* COUNTER_NAME:
* architectures:
* gfxXX: // Can be more than one, / deliminated if they share idential data
* block: <Optional>
* event: <Optional>
* expression: <optional>
* description: <Optional>
* gfxYY:
* ...
* description: General counter desctiption
*/
MetricMap
loadXml(const std::string& filename, bool load_constants = false)
loadYAML(const std::string& filename, bool load_constants = false, bool load_derived = false)
{
MetricMap ret;
ROCP_INFO << "Loading Counter Config: " << filename;
// todo: return unique_ptr....
auto xml = common::Xml::Create(filename);
ROCP_FATAL_IF(!xml)
<< "Could not open XML Counter Config File (set env ROCPROFILER_METRICS_PATH)";
auto yaml = YAML::LoadFile(filename);
const auto& constant_metrics = get_constants();
for(const auto& [gfx_name, nodes] : xml->GetAllNodes())
for(auto it = yaml.begin(); it != yaml.end(); ++it)
{
/**
* "top." is used to designate the root encapsulation of all contained XML subroots (in our
* case "gfxX"). This is inserted by the parser so it will always be present. .metric
* denotes XML tags that are contained in the subroots. This will not change unless we
* respec the XML (which we should...).
*/
if(gfx_name.find("metric") == std::string::npos ||
gfx_name.find("top.") == std::string::npos || gfx_name.find("gfx") == std::string::npos)
continue;
auto counter_name = it->first.as<std::string>();
auto counter_def = it->second;
auto def_iterator = counter_def["architectures"];
auto& metricVec =
ret.emplace(gfx_name.substr(strlen("top."),
gfx_name.size() - strlen("top.") - strlen(".metric")),
std::vector<Metric>())
.first->second;
for(const auto& node : nodes)
for(auto def_it = def_iterator.begin(); def_it != def_iterator.end(); ++def_it)
{
metricVec.emplace_back(gfx_name,
node->opts["name"],
node->opts["block"],
node->opts["event"],
node->opts["descr"],
node->opts["expr"],
node->opts["special"],
current_id());
current_id()++;
}
auto archs = def_it->first.as<std::string>();
auto def = def_it->second;
// To save space in the YAML file, we combine architectures with the same
// definition into a single entry. Split these out into separate entries.
// architectures:
// gfx10/gfx1010/gfx1030/gfx1031/.....9:
// expression: 400*SQ_WAIT_INST_LDS/SQ_WAVES/GRBM_GUI_ACTIVE
std::vector<std::string> result;
std::stringstream ss(archs);
std::string arch_name;
if(load_constants)
{
metricVec.insert(metricVec.end(), constant_metrics.begin(), constant_metrics.end());
while(std::getline(ss, arch_name, '/'))
{
auto& metricVec = ret.emplace(arch_name, std::vector<Metric>()).first->second;
if(metricVec.empty() && load_constants)
{
metricVec.insert(
metricVec.end(), get_constants().begin(), get_constants().end());
}
if((def["expression"] && load_derived) || (!load_derived && !def["expression"]))
{
std::string description;
if(def["description"])
description = def["description"].as<std::string>();
else if(counter_def["description"])
description = counter_def["description"].as<std::string>();
metricVec.emplace_back(
arch_name,
counter_name,
(def["block"] ? def["block"].as<std::string>() : ""),
(def["event"] ? def["event"].as<std::string>() : ""),
description,
(def["expression"] ? def["expression"].as<std::string>() : ""),
"",
current_id());
current_id()++;
ROCP_TRACE << fmt::format("Inserted info {}: {}", arch_name, metricVec.back());
}
}
}
}
ROCP_FATAL_IF(current_id() > 65536)
<< "Counter count exceeds 16 bits, which may break counter id output";
return ret;
@@ -163,19 +192,19 @@ findViaEnvironment(const std::string& filename)
MetricMap
getDerivedHardwareMetrics()
{
auto counters_path = findViaEnvironment("derived_counters.xml");
auto counters_path = findViaEnvironment("counter_defs.yaml");
ROCP_FATAL_IF(!common::filesystem::exists(counters_path))
<< "metric xml file '" << counters_path << "' does not exist";
return loadXml(counters_path);
return loadYAML(counters_path, false, true);
}
MetricMap
getBaseHardwareMetrics()
{
auto counters_path = findViaEnvironment("basic_counters.xml");
auto counters_path = findViaEnvironment("counter_defs.yaml");
ROCP_FATAL_IF(!common::filesystem::exists(counters_path))
<< "metric xml file '" << counters_path << "' does not exist";
return loadXml(counters_path, true);
return loadYAML(counters_path, true, false);
}
const MetricIdMap*