Files
TheRock/rocm-libraries/shared/tensile/Tensile/Source/client/source/ResultFileReporter.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

316 lines
13 KiB
C++

/*******************************************************************************
*
* MIT License
*
* Copyright (C) 2019-2022 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 <ResultFileReporter.hpp>
#include <cstddef>
#include <sstream>
namespace Tensile
{
namespace Client
{
std::shared_ptr<ResultFileReporter>
ResultFileReporter::Default(po::variables_map const& args)
{
return std::make_shared<ResultFileReporter>(
args["results-file"].as<std::string>(),
args["csv-export-extra-cols"].as<bool>(),
args["csv-merge-same-problems"].as<bool>(),
args["performance-metric"].as<PerformanceMetric>());
}
ResultFileReporter::ResultFileReporter(std::string const& filename,
bool exportExtraCols,
bool mergeSameProblems,
PerformanceMetric performanceMetric)
: m_output(filename)
, m_extraCol(exportExtraCols)
, m_mergeSameProblems(mergeSameProblems)
, m_performanceMetric(performanceMetric)
{
if(m_performanceMetric == PerformanceMetric::CUEfficiency)
m_output.setHeaderForKey(ResultKey::ProblemIndex, "GFlopsPerCU");
else // Default to 'DeviceEfficiency' benchmarking if CUEfficiency not specified
m_output.setHeaderForKey(ResultKey::ProblemIndex, "GFlops");
}
template <typename T>
void ResultFileReporter::reportValue(std::string const& key, T const& value)
{
std::ostringstream ss;
ss << value;
std::string valueStr = ss.str();
if(key == ResultKey::Validation)
{
if(valueStr != "PASSED" && valueStr != "NO_CHECK")
{
m_output.setValueForKey(m_solutionName, -1.0);
m_invalidSolution = true;
}
}
else if(key == ResultKey::SolutionName)
{
m_solutionName = valueStr;
m_output.setHeaderForKey(valueStr, valueStr);
}
else if(key == ResultKey::TimeUS)
{
// cascade from BenchmarkTimer, Time-US first
++m_currSolutionIdx;
if(!m_invalidSolution)
{
double timeUS = std::stod(valueStr);
if(m_fasterTimeUS < 0 || m_fasterTimeUS > timeUS)
{
m_fasterTimeUS = timeUS;
}
}
}
else if((key == ResultKey::SpeedGFlops
&& m_performanceMetric == PerformanceMetric::DeviceEfficiency)
|| (key == ResultKey::SpeedGFlopsPerCu
&& m_performanceMetric == PerformanceMetric::CUEfficiency))
{
// cascade from BenchmarkTimer, SpeedGFlops or SpeedGFlopsPerCU second
if(!m_invalidSolution)
{
m_output.setValueForKey(m_solutionName, value);
double gflops = std::stod(valueStr);
if(m_fastestGflops < gflops)
{
m_winnerSolution = m_solutionName;
m_winnerSolutionIdx = m_currSolutionIdx;
m_fastestGflops = gflops;
m_winnerGfxClock = m_currGfxClock;
m_winnerPower = m_currPower;
m_winnerTemperatureHot = m_currTemperatureHot;
}
}
}
else if(key == ResultKey::GfxFrequency)
{
m_currGfxClock = static_cast<uint16_t>(std::stoi(valueStr));
}
else if(key == ResultKey::Power)
{
m_currPower = static_cast<uint16_t>(std::stoi(valueStr));
}
else if(key == ResultKey::TemperatureHot)
{
m_currTemperatureHot = static_cast<uint16_t>(std::stoi(valueStr));
}
else
{
m_output.setValueForKey(key, value);
}
}
void ResultFileReporter::reportValue_string(std::string const& key,
std::string const& value)
{
reportValue(key, value);
}
void ResultFileReporter::reportValue_uint(std::string const& key, uint64_t value)
{
reportValue(key, value);
}
void ResultFileReporter::reportValue_int(std::string const& key, int64_t value)
{
reportValue(key, value);
}
void ResultFileReporter::reportValue_double(std::string const& key, double value)
{
reportValue(key, value);
}
void ResultFileReporter::reportValue_sizes(std::string const& key,
std::vector<size_t> const& value)
{
if(key == ResultKey::ProblemSizes)
{
for(size_t i = 0; i < value.size(); i++)
{
std::string key = concatenate("Size", static_cast<char>('I' + i));
m_output.setHeaderForKey(key, key);
m_output.setValueForKey(key, value[i]);
}
// Values for these come separately.
m_output.setHeaderForKey(ResultKey::LDD, "LDD");
m_output.setHeaderForKey(ResultKey::LDC, "LDC");
m_output.setHeaderForKey(ResultKey::LDA, "LDA");
m_output.setHeaderForKey(ResultKey::LDB, "LDB");
m_output.setHeaderForKey(ResultKey::GfxFrequency, "WinnerFreq");
if(m_extraCol)
{
m_output.setHeaderForKey(ResultKey::FastestGFlops, "WinnerGFlops");
m_output.setHeaderForKey(ResultKey::TimeUS, "WinnerTimeUS");
m_output.setHeaderForKey(ResultKey::SolutionWinnerIdx, "WinnerIdx");
m_output.setHeaderForKey(ResultKey::SolutionWinner, "WinnerName");
}
m_output.setHeaderForKey(ResultKey::TotalFlops, "TotalFlops");
m_output.setHeaderForKey(ResultKey::Power, "WinnerPower");
m_output.setHeaderForKey(ResultKey::TemperatureHot, "WinnerTemperature");
}
}
void ResultFileReporter::mergeRow(std::unordered_map<std::string, std::string>& newRow)
{
m_currProbID = std::stoull(newRow[ResultKey::ProblemIndex]);
if(m_probMap.count(m_currProbID) == 0)
{
m_probMap[m_currProbID] = newRow;
return;
}
auto& oldRow = m_probMap[m_currProbID];
for(auto& oldRowIter : oldRow)
{
const std::string& key = oldRowIter.first;
if(key.compare(ResultKey::ProblemIndex) == 0
|| key.find("Size") != std::string::npos || key.compare(ResultKey::LDD) == 0
|| key.compare(ResultKey::LDC) == 0 || key.compare(ResultKey::LDA) == 0
|| key.compare(ResultKey::LDB) == 0 || key.compare(ResultKey::TotalFlops) == 0)
{
// these data should be the same for same problem
assert(oldRowIter.second == newRow[key]);
}
else if(key.compare(ResultKey::FastestGFlops) == 0)
{
// if new row is better, update, dummy guard for -1 and empty str
int64_t oldFastest
= (oldRowIter.second.empty()) ? 0 : std::stoll(oldRowIter.second);
int64_t newFastest = (newRow[key].empty()) ? 0 : std::stoll(newRow[key]);
if(newFastest > oldFastest)
{
oldRow[ResultKey::FastestGFlops] = newRow[ResultKey::FastestGFlops];
oldRow[ResultKey::TimeUS] = newRow[ResultKey::TimeUS];
oldRow[ResultKey::SolutionWinnerIdx] = newRow[ResultKey::SolutionWinnerIdx];
oldRow[ResultKey::SolutionWinner] = newRow[ResultKey::SolutionWinner];
oldRow[ResultKey::GfxFrequency] = newRow[ResultKey::GfxFrequency];
oldRow[ResultKey::Power] = newRow[ResultKey::Power];
oldRow[ResultKey::TemperatureHot] = newRow[ResultKey::TemperatureHot];
}
}
else if(key.compare(ResultKey::TimeUS) == 0
|| key.compare(ResultKey::SolutionWinnerIdx) == 0
|| key.compare(ResultKey::SolutionWinner) == 0
|| key.compare(ResultKey::GfxFrequency) == 0
|| key.compare(ResultKey::Power) == 0
|| key.compare(ResultKey::TemperatureHot) == 0)
{
// skip, we update these together with FastestGFlops
continue;
}
else
{
// these are gflops for each solution
// if new row is better, update. Dummy guard for -1 and empty str
int64_t oldFastest
= (oldRowIter.second.empty()) ? 0 : std::stoll(oldRowIter.second);
int64_t newFastest = (newRow[key].empty()) ? 0 : std::stoll(newRow[key]);
if(newFastest > oldFastest)
{
oldRow[key] = newRow[key];
}
}
}
}
void ResultFileReporter::postProblem()
{
if(m_extraCol)
{
// update winner
m_output.setValueForKey(ResultKey::FastestGFlops, m_fastestGflops);
m_output.setValueForKey(ResultKey::TimeUS, m_fasterTimeUS);
m_output.setValueForKey(ResultKey::SolutionWinnerIdx, m_winnerSolutionIdx);
m_output.setValueForKey(ResultKey::SolutionWinner, m_winnerSolution);
}
m_output.setValueForKey(ResultKey::GfxFrequency, m_winnerGfxClock);
m_output.setValueForKey(ResultKey::Power, m_winnerPower);
m_output.setValueForKey(ResultKey::TemperatureHot, m_winnerTemperatureHot);
// reset
m_winnerSolution = "";
m_currSolutionIdx = -1;
m_winnerSolutionIdx = -1;
m_fastestGflops = -1.0;
m_fasterTimeUS = -1.0;
m_currGfxClock = 0;
m_winnerGfxClock = 0;
m_currGfxClock = 0;
m_winnerGfxClock = 0;
m_currPower = 0;
m_winnerPower = 0;
m_currTemperatureHot = 0;
m_winnerTemperatureHot = 0;
if(!m_mergeSameProblems)
{
m_output.writeCurrentRow();
}
else
{
std::unordered_map<std::string, std::string> curRow;
m_output.readCurrentRow(curRow);
m_output.clearCurrentRow();
// for (auto & field : curRow )
// std::cout << "key:" << field.first << ", value:" << field.second << std::endl;
this->mergeRow(curRow);
}
}
void ResultFileReporter::postSolution()
{
m_solutionName = "";
m_invalidSolution = false;
}
void ResultFileReporter::finalizeReport()
{
if(m_mergeSameProblems)
{
for(auto& probIter : m_probMap)
{
auto& single_row = probIter.second;
for(auto& field : single_row)
{
m_output.setValueForKey(field.first, field.second);
}
m_output.writeCurrentRow();
}
}
}
} // namespace Client
} // namespace Tensile