Files
rocm-systems/source/lib/rocprofiler/counters/tests/evaluate_ast_test.cpp
T
Jonathan R. Madsen 086218c2eb Fixes licensing in files (#206)
* Update LICENSE

- fix inconsistencies

* Revert lib/rocprofiler/counters/parser/scanner.cpp

* Update lib/rocprofiler/counters/tests/dimension.cpp

- revert ending curly brace

* Revert missing curly braces

- missing curly braces when file did not end with a new line
2023-11-14 10:58:33 -06:00

286 řádky
11 KiB
C++

// MIT License
//
// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <cstdint>
#include <tuple>
#include <fmt/core.h>
#include <gtest/gtest.h>
#include "evaluate_ast_test.hpp"
#include "lib/rocprofiler/counters/parser/reader.hpp"
namespace
{
ReduceOperation
get_reduce_op_type_from_string(const std::string& op)
{
static const std::unordered_map<std::string, ReduceOperation> reduce_op_string_to_type = {
{"min", REDUCE_MIN}, {"max", REDUCE_MAX}, {"sum", REDUCE_SUM}, {"avr", REDUCE_AVG}};
ReduceOperation type = REDUCE_NONE;
const auto* reduce_op_type = rocprofiler::common::get_val(reduce_op_string_to_type, op);
if(reduce_op_type) type = *reduce_op_type;
return type;
}
bool
isIdentical(const EvaluateAST& eval_ast, const RawAST& raw_ast)
{
if(raw_ast.counter_set.size() != eval_ast.children().size() ||
raw_ast.type != eval_ast.type() ||
get_reduce_op_type_from_string(raw_ast.reduce_op) != eval_ast.reduce_op())
{
return false;
}
for(size_t i = 0; i < raw_ast.counter_set.size(); i++)
{
if(!isIdentical(eval_ast.children()[i], *raw_ast.counter_set[i]))
{
return false;
}
}
return true;
}
} // namespace
TEST(evaluate_ast, basic_copy)
{
std::unordered_map<std::string, Metric> metrics = {
{"SQ_WAVES", Metric("gfx9", "a", "a", "a", "a", "a", "", 0)},
{"TCC_HIT", Metric("gfx9", "b", "b", "b", "b", "b", "", 1)}};
RawAST* ast = nullptr;
auto* buf = yy_scan_string("SQ_WAVES + TCC_HIT");
yyparse(&ast);
ASSERT_TRUE(ast);
auto eval_ast = EvaluateAST(metrics, *ast, "gfx9");
EXPECT_TRUE(isIdentical(eval_ast, *ast));
yy_delete_buffer(buf);
delete ast;
}
TEST(evaluate_ast, counter_expansion)
{
std::unordered_map<std::string, Metric> metrics = {
{"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)},
{"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)},
{"TEST_DERRIVED",
Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+TCC_HIT", "", 2)}};
std::unordered_map<std::string, EvaluateAST> asts;
for(auto [val, metric] : metrics)
{
RawAST* ast = nullptr;
auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str()
: metric.expression().c_str());
yyparse(&ast);
ASSERT_TRUE(ast);
asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9")));
yy_delete_buffer(buf);
delete ast;
}
std::set<Metric> required_counters;
asts.at("TEST_DERRIVED").get_required_counters(asts, required_counters);
EXPECT_EQ(required_counters.size(), 2);
auto expected = std::set<Metric>{{Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1),
Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}};
for(auto& counter_found : required_counters)
{
EXPECT_NE(expected.find(counter_found), expected.end());
}
}
TEST(evaluate_ast, counter_expansion_multi_derived)
{
std::unordered_map<std::string, Metric> metrics = {
{"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)},
{"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)},
{"TEST_DERRIVED",
Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+TCC_HIT", "", 2)},
{"TEST_DERRIVED3",
Metric("gfx9", "TEST_DERRIVED3", "C", "C", "C", "TEST_DERRIVED+SQ_WAVES+TCC_HIT", "", 3)}};
std::unordered_map<std::string, EvaluateAST> asts;
for(auto [val, metric] : metrics)
{
RawAST* ast = nullptr;
auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str()
: metric.expression().c_str());
yyparse(&ast);
ASSERT_TRUE(ast);
asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9")));
yy_delete_buffer(buf);
delete ast;
}
std::set<Metric> required_counters;
asts.at("TEST_DERRIVED3").get_required_counters(asts, required_counters);
EXPECT_EQ(required_counters.size(), 2);
auto expected = std::set<Metric>{{Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1),
Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}};
for(auto& counter_found : required_counters)
{
EXPECT_NE(expected.find(counter_found), expected.end());
}
}
TEST(evaluate_ast, counter_expansion_order)
{
std::unordered_map<std::string, Metric> metrics = {
{"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)},
{"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)},
{"VLL", Metric("gfx9", "VLL", "b", "b", "b", "", "", 4)},
{"TEST_DERRIVED", Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+VLL", "", 2)},
{"TEST_DERRIVED3",
Metric("gfx9", "TEST_DERRIVED3", "C", "C", "C", "TEST_DERRIVED+SQ_WAVES+TCC_HIT", "", 3)}};
std::unordered_map<std::string, EvaluateAST> asts;
for(auto [val, metric] : metrics)
{
RawAST* ast = nullptr;
auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str()
: metric.expression().c_str());
yyparse(&ast);
ASSERT_TRUE(ast);
asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9")));
yy_delete_buffer(buf);
delete ast;
}
std::set<Metric> required_counters;
asts.at("TEST_DERRIVED3").get_required_counters(asts, required_counters);
EXPECT_EQ(required_counters.size(), 3);
auto expected = std::set<Metric>{{Metric("gfx9", "VLL", "b", "b", "b", "", "", 4),
Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1),
Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)}};
for(auto& counter_found : required_counters)
{
EXPECT_NE(expected.find(counter_found), expected.end());
}
}
// TEST(evaluate_ast, counter_expansion_function)
// {
// std::unordered_map<std::string, Metric> metrics = {
// {"SQ_WAVES", Metric("gfx9", "SQ_WAVES", "a", "a", "a", "", "", 0)},
// {"TCC_HIT", Metric("gfx9", "TCC_HIT", "b", "b", "b", "", "", 1)},
// {"VLL", Metric("gfx9", "VLL", "b", "b", "b", "", "", 4)},
// {"TEST_DERRIVED", Metric("gfx9", "TEST_DERRIVED", "C", "C", "C", "SQ_WAVES+VLL", "",
// 2)}};
// std::unordered_map<std::string, EvaluateAST> asts;
// for(auto [val, metric] : metrics)
// {
// RawAST* ast = nullptr;
// auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str()
// : metric.expression().c_str());
// yyparse(&ast);
// ASSERT_TRUE(ast) << metric.expression() << " " << metric.name();
// asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9")));
// yy_delete_buffer(buf);
// delete ast;
// }
// }
// TEST(evaluate_ast, evaluate_simple_math)
// {
// std::unordered_map<std::string, Metric> metrics;
// std::unordered_map<uint64_t, metric_result> results_map;
// std::unordered_map<uint64_t, std::vector<double>> expected_values;
// uint64_t id = 0;
// for(auto& data : test_data_evaluate_simple_math)
// {
// metrics.emplace(
// data.name, Metric("gfx9", data.name, "Block", "0", "", data.expr, "", id));
// metric_result res = {id, data.sample_values};
// results_map.emplace(id, res);
// expected_values.emplace(id, data.expected_values);
// ++id;
// }
// std::unordered_map<std::string, EvaluateAST> asts;
// for(auto [val, metric] : metrics)
// {
// RawAST* ast = nullptr;
// auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str()
// : metric.expression().c_str());
// yyparse(&ast);
// ASSERT_TRUE(ast);
// asts.emplace(val, std::move(EvaluateAST(metrics, *ast, "gfx9")));
// yy_delete_buffer(buf);
// delete ast;
// }
// for(auto [metric_name, ast] : asts)
// {
// double value = ast.evaluate(results_map);
// uint64_t metric_id = metrics.at(metric_name).id();
// EXPECT_EQ(value, expected_values.at(metric_id)[0]);
// }
// }
// TEST(evaluate_ast, evaluate_evaluate_simple_reduce)
// {
// std::unordered_map<std::string, Metric> metrics;
// std::unordered_map<uint64_t, metric_result> results_map;
// std::unordered_map<uint64_t, std::vector<double>> expected_values;
// uint64_t id = 0;
// for(auto& data : test_data_evaluate_simple_reduce)
// {
// metrics.emplace(
// data.name, Metric("gfx9", data.name, "Block", "0", "", data.expr, "", id));
// metric_result res = {id, data.sample_values};
// results_map.emplace(id, res);
// expected_values.emplace(id, data.expected_values);
// ++id;
// }
// std::unordered_map<std::string, EvaluateAST> asts;
// for(auto [val, metric] : metrics)
// {
// RawAST* ast = nullptr;
// auto buf = yy_scan_string(metric.expression().empty() ? metric.name().c_str()
// : metric.expression().c_str());
// yyparse(&ast);
// ASSERT_TRUE(ast);
// asts.emplace(val, EvaluateAST(metrics, *ast, "gfx9"));
// yy_delete_buffer(buf);
// delete ast;
// }
// for(auto [metric_name, ast]: asts){
// double value = ast.evaluate(results_map);
// uint64_t metric_id = metrics.at(metric_name).id();
// EXPECT_EQ(value, expected_values.at(metric_id)[0]);
// }
// }