Files
TheRock/rocm-libraries/projects/rocthrust/benchmark/bench_utils/custom_reporter.hpp
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

827 lines
23 KiB
C++

// MIT License
//
// Copyright (c) 2024-2025 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.
#ifndef ROCTHRUST_BENCHMARKS_BENCH_UTILS_CUSTOM_REPORTER_HPP_
#define ROCTHRUST_BENCHMARKS_BENCH_UTILS_CUSTOM_REPORTER_HPP_
// Utils
#include "common/types.hpp"
// Google Benchmark
#include <benchmark/benchmark.h>
// STL
#include <algorithm>
#include <cstdarg>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <ostream>
#include <string>
#include <vector>
namespace bench_utils
{
template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
// Check if the src can be casted to the DstType
return dynamic_cast<const DstType*>(src) != nullptr;
}
static std::string FormatString(const char* msg, va_list args)
{
// we might need a second shot at this, so pre-emptivly make a copy
va_list args_cp;
va_copy(args_cp, args);
std::size_t size = 256;
char local_buff[256];
auto ret = vsnprintf(local_buff, size, msg, args_cp);
if (ret <= 0)
{
return {};
}
else if (static_cast<size_t>(ret) < size)
{
return local_buff;
}
// we did not provide a long enough buffer on our first attempt.
size = static_cast<size_t>(ret) + 1; // + 1 for the null byte
std::unique_ptr<char[]> buff(new char[size]);
ret = vsnprintf(buff.get(), size, msg, args);
return buff.get();
}
static std::string FormatString(const char* msg, ...)
{
va_list args;
va_start(args, msg);
auto tmp = FormatString(msg, args);
va_end(args);
return tmp;
}
std::string get_complexity(const benchmark::BigO& complexity)
{
switch (complexity)
{
case benchmark::oN:
return "N";
case benchmark::oNSquared:
return "N^2";
case benchmark::oNCubed:
return "N^3";
case benchmark::oLogN:
return "lgN";
case benchmark::oNLogN:
return "NlgN";
case benchmark::o1:
return "(1)";
default:
return "f(N)";
}
}
template <class Run>
double calculate_bw_utils(const Run& result)
{
// Calculates bandwith utilization in %
std::map<std::string, std::string>* global_context = benchmark::internal::GetGlobalContext();
if (global_context != nullptr)
{
for (const auto& keyval : *global_context)
{
if (keyval.first == "hdp_peak_global_mem_bus_bandwidth")
{
const double global_mem_bw = result.counters.at("bytes_per_second").value;
const double peak_global_bw = std::stod(keyval.second);
const double bw_util = 100. * global_mem_bw / peak_global_bw;
return bw_util;
}
}
}
return -1;
}
/// \brief Custom Google Benchmark reporter for formatting the benchmarks' report matching Thrust's.
///
/// This reporter is a ConsoleReporter that outputs:
/// - GPU Time: measured with events and registered as manual time.
/// - CPU Time: measured by Google Benchmark.
/// - Iterations: the number of kernel executions done on each benchmark run.
/// - GlobalMem BW: number of GB read and written to global memory per second of execution.
/// - BW util: percentage of the theoretical peak global memory bandwith utilised by the benchmark.
/// - Elements/s: number of G elements (G = 10**6) processed by second of execution.
/// - Labels: for extra labels. For instance, labels are used by the benchmarks generating random
/// input values to report the seed used.
///
/// Additionally, when the number of \p repetitions is greater than one, each benchmark run is
/// repeated \p repetitions times to measure the stability of results. In this case, the mean,
/// median, standard deviation (stddev) and coefficient of variation (cv) of the above-described
/// metrics are also reported after all the \p repetitions have ben run.
class CustomConsoleReporter : public benchmark::ConsoleReporter
{
private:
enum LogColor
{
COLOR_DEFAULT,
COLOR_RED,
COLOR_GREEN,
COLOR_YELLOW,
COLOR_BLUE,
COLOR_CYAN,
COLOR_WHITE
};
std::string get_log_color(LogColor&& color)
{
std::string s("unknown");
switch (color)
{
case COLOR_RED:
return "\033[31m";
case COLOR_GREEN:
return "\033[32m";
case COLOR_YELLOW:
return "\033[33m";
case COLOR_BLUE:
return "\033[34m";
case COLOR_CYAN:
return "\033[36m";
case COLOR_WHITE:
return "\033[37m";
default: // COLOR_DEFAULT
return "\033[0m";
}
}
void PrintColoredString(std::ostream& os, std::string color, std::string str, ...)
{
os << color;
va_list args;
va_start(args, str);
os << FormatString(str.data(), args);
va_end(args);
}
static std::string FormatTime(double time)
{
// Assuming the time is at max 9.9999e+99 and we have 10 digits for the
// number, we get 10-1(.)-1(e)-1(sign)-2(exponent) = 5 digits to print.
if (time > 9999999999 /*max 10 digit number*/)
{
return FormatString("%1.4e", time);
}
return FormatString("%10.3f", time);
}
public:
void PrintHeader(const Run& /*run*/)
{
// Assume run.counters (with elements processed and global mem reads/writes)
// will not be empty
std::string str = FormatString(
"%-*s %13s %15s %12s %16s %12s %14s %14s",
static_cast<int>(name_field_width_),
"Benchmark",
"GPU Time",
"CPU Time",
"Iterations",
"GlobalMem BW",
"BW util",
"GPU Noise",
"Elements/s");
std::string line = std::string(str.length(), '-');
GetOutputStream() << line << "\n" << str << "\n" << line << "\n";
}
void PrintRunData(const Run& result)
{
// Report benchmark name
auto& sout = GetOutputStream();
auto color = get_log_color((result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN);
PrintColoredString(sout, color, "%-*s ", name_field_width_, result.benchmark_name().c_str());
if (benchmark::internal::SkippedWithError == result.skipped)
{
PrintColoredString(sout, get_log_color(COLOR_RED), "ERROR OCCURRED: \'%s\'", result.skip_message.c_str());
PrintColoredString(sout, get_log_color(COLOR_DEFAULT), "\n");
return;
}
else if (benchmark::internal::SkippedWithMessage == result.skipped)
{
PrintColoredString(sout, get_log_color(COLOR_WHITE), "SKIPPED: \'%s\'", result.skip_message.c_str());
PrintColoredString(sout, get_log_color(COLOR_DEFAULT), "\n");
return;
}
// Report GPU and CPU time
const double gpu_time = result.GetAdjustedRealTime();
const double cpu_time = result.GetAdjustedCPUTime();
const std::string gpu_time_str = FormatTime(gpu_time);
const std::string cpu_time_str = FormatTime(cpu_time);
if (result.report_big_o)
{
std::string big_o = get_complexity(result.complexity);
PrintColoredString(
sout, get_log_color(COLOR_YELLOW), "%10.3f %-4s %10.3f %-4s ", gpu_time, big_o.c_str(), cpu_time, big_o.c_str());
}
else if (result.report_rms)
{
PrintColoredString(
sout, get_log_color(COLOR_YELLOW), "%10.3f %-4s %10.3f %-4s ", gpu_time * 100, "%", cpu_time * 100, "%");
}
else if (result.run_type != Run::RT_Aggregate || result.aggregate_unit == benchmark::StatisticUnit::kTime)
{
const char* timeLabel = GetTimeUnitString(result.time_unit);
PrintColoredString(
sout,
get_log_color(COLOR_YELLOW),
"%s %-4s %s %-4s ",
gpu_time_str.c_str(),
timeLabel,
cpu_time_str.c_str(),
timeLabel);
}
else
{
assert(result.aggregate_unit == benchmark::StatisticUnit::kPercentage);
PrintColoredString(
sout,
get_log_color(COLOR_YELLOW),
"%10.3f %-4s %10.3f %-4s ",
(100. * result.real_accumulated_time),
"%",
(100. * result.cpu_accumulated_time),
"%");
}
// Report iterations
if (!result.report_big_o && !result.report_rms)
{
PrintColoredString(sout, get_log_color(COLOR_CYAN), "%10lld", result.iterations);
}
// Report counters
std::string s;
const char* unit = "";
for (auto& c : result.counters)
{
std::size_t cNameLen = std::max(std::string::size_type(10), c.first.length());
if (c.first == "items_per_second")
{
// Print elements processed in G/s
if (result.run_type == Run::RT_Aggregate && result.aggregate_unit == benchmark::StatisticUnit::kPercentage)
{
s = FormatString("%.3f", 100. * c.second.value);
unit = "%";
}
else
{
s = FormatString("%.3f", c.second.value / 1e9);
unit = "G";
}
}
else if (c.first == "bytes_per_second")
{
// Print GlobalMem BW in GB/s
if (result.run_type == Run::RT_Aggregate && result.aggregate_unit == benchmark::StatisticUnit::kPercentage)
{
s = FormatString("%.3f", 100. * c.second.value);
unit = "%";
}
else
{
s = FormatString("%.3f", c.second.value / 1e9);
if (c.second.flags & benchmark::Counter::kIsRate)
{
unit = "GB/s";
}
}
PrintColoredString(sout, get_log_color(COLOR_DEFAULT), " %*s%s", cNameLen - strlen(unit), s.c_str(), unit);
// Print BW util
s = FormatString("%.2f", c.second.value);
const double bw_util = calculate_bw_utils(result);
if (bw_util >= 0)
{
s = FormatString("%.2f", bw_util);
unit = "%";
cNameLen = std::max(std::string::size_type(12), s.length());
}
}
else if (c.first == "gpu_noise")
{
if (result.run_type == Run::RT_Aggregate && result.aggregate_unit == benchmark::StatisticUnit::kPercentage)
{
s = FormatString("%.2f", 100. * c.second.value);
}
else
{
s = FormatString("%.2f", c.second.value);
}
unit = "%";
}
else
{
if (result.run_type == Run::RT_Aggregate && result.aggregate_unit == benchmark::StatisticUnit::kPercentage)
{
s = FormatString("%.2f", 100. * c.second.value);
unit = "%";
}
else
{
s = FormatString("%.2f", c.second.value / 1000.);
if (c.second.flags & benchmark::Counter::kIsRate)
{
unit = (c.second.flags & benchmark::Counter::kInvert) ? "s" : "/s";
}
}
}
PrintColoredString(sout, get_log_color(COLOR_DEFAULT), " %*s%s", cNameLen - strlen(unit), s.c_str(), unit);
}
// Print labels, that is, GPU noise
if (!result.report_label.empty())
{
std::string s = FormatString("%.2f", 100. * std::stod(result.report_label));
const char* unit = "%";
PrintColoredString(sout, get_log_color(COLOR_DEFAULT), " %13s%s", s.c_str(), unit);
}
PrintColoredString(sout, get_log_color(COLOR_DEFAULT), "\n");
}
// Called once for each group of benchmark runs, gives information about
// cpu-time, gpu-time, elements processed, global memory bw and the %
// the latter represents from the peak global bandwidth during the
// benchmark run. If the group of runs contained more than two entries
// then 'report' contains additional elements representing the mean,
// standard deviation and coefficient of variation of those runs.
// Additionally if this group of runs was the last in a family of
// benchmarks, 'reports' contains additional entries representing the
// asymptotic complexity and RMS of that benchmark family.
void ReportRuns(const std::vector<Run>& reports)
{
for (const auto& run : reports)
{
// Print the header if none was printed yet
bool print_header = !printed_header_;
if (print_header)
{
printed_header_ = true;
PrintHeader(run);
}
PrintRunData(run);
}
}
};
class CustomJSONReporter : public benchmark::JSONReporter
{
private:
bool first_report_ = true;
std::string StrEscape(const std::string& s)
{
std::string tmp;
tmp.reserve(s.size());
for (char c : s)
{
switch (c)
{
case '\b':
tmp += "\\b";
break;
case '\f':
tmp += "\\f";
break;
case '\n':
tmp += "\\n";
break;
case '\r':
tmp += "\\r";
break;
case '\t':
tmp += "\\t";
break;
case '\\':
tmp += "\\\\";
break;
case '"':
tmp += "\\\"";
break;
default:
tmp += c;
break;
}
}
return tmp;
}
std::string FormatKV(std::string const& key, std::string const& value)
{
return FormatString("\"%s\": \"%s\"", StrEscape(key).c_str(), StrEscape(value).c_str());
}
std::string FormatKV(std::string const& key, const char* value)
{
return FormatString("\"%s\": \"%s\"", StrEscape(key).c_str(), StrEscape(value).c_str());
}
std::string FormatKV(std::string const& key, bool value)
{
return FormatString("\"%s\": %s", StrEscape(key).c_str(), value ? "true" : "false");
}
std::string FormatKV(std::string const& key, int64_t value)
{
std::stringstream ss;
ss << '"' << StrEscape(key) << "\": " << value;
return ss.str();
}
std::string FormatKV(std::string const& key, double value)
{
std::stringstream ss;
ss << '"' << StrEscape(key) << "\": ";
if (std::isnan(value))
{
ss << (value < 0 ? "-" : "") << "NaN";
}
else if (std::isinf(value))
{
ss << (value < 0 ? "-" : "") << "Infinity";
}
else
{
const auto max_digits10 = std::numeric_limits<decltype(value)>::max_digits10;
const auto max_fractional_digits10 = max_digits10 - 1;
ss << std::scientific << std::setprecision(max_fractional_digits10) << value;
}
return ss.str();
}
public:
void ReportRuns(std::vector<Run> const& reports)
{
if (reports.empty())
{
return;
}
std::string indent(4, ' ');
std::ostream& out = GetOutputStream();
if (!first_report_)
{
out << ",\n";
}
first_report_ = false;
for (auto it = reports.begin(); it != reports.end(); ++it)
{
out << indent << "{\n";
PrintRunData(*it);
out << indent << '}';
auto it_cp = it;
if (++it_cp != reports.end())
{
out << ",\n";
}
}
}
void PrintRunData(Run const& run)
{
std::string indent(6, ' ');
std::ostream& out = GetOutputStream();
auto output_format = [this, &out, &indent](const std::string& label, auto val, bool start_endl = true) {
if (start_endl)
{
out << ",\n";
}
out << indent << FormatKV(label, val);
};
output_format("name", run.benchmark_name(), false);
output_format("family_index", run.family_index);
output_format("per_family_instance_index", run.per_family_instance_index);
output_format("run_name", run.run_name.str());
output_format("run_type", [&run]() -> const char* {
switch (run.run_type)
{
case BenchmarkReporter::Run::RT_Iteration:
return "iteration";
case BenchmarkReporter::Run::RT_Aggregate:
return "aggregate";
}
BENCHMARK_UNREACHABLE();
}());
output_format("repetitions", run.repetitions);
if (run.run_type != BenchmarkReporter::Run::RT_Aggregate)
{
output_format("repetition_index", run.repetition_index);
}
output_format("threads", run.threads);
if (run.run_type == BenchmarkReporter::Run::RT_Aggregate)
{
output_format("aggregate_name", run.aggregate_name);
output_format("aggregate_unit", [&run]() -> const char* {
switch (run.aggregate_unit)
{
case benchmark::StatisticUnit::kTime:
return "time";
case benchmark::StatisticUnit::kPercentage:
return "percentage";
}
BENCHMARK_UNREACHABLE();
}());
}
if (benchmark::internal::SkippedWithError == run.skipped)
{
output_format("error_occurred", true);
output_format("error_message", run.skip_message);
}
else if (benchmark::internal::SkippedWithMessage == run.skipped)
{
output_format("skipped", true);
output_format("skip_message", run.skip_message);
}
if (!run.report_big_o && !run.report_rms)
{
output_format("iterations", run.iterations);
if (run.run_type != Run::RT_Aggregate || run.aggregate_unit == benchmark::StatisticUnit::kTime)
{
output_format("gpu_time", run.GetAdjustedRealTime());
output_format("cpu_time", run.GetAdjustedCPUTime());
}
else
{
assert(run.aggregate_unit == benchmark::StatisticUnit::kPercentage);
output_format("gpu_time", run.real_accumulated_time);
output_format("cpu_time", run.cpu_accumulated_time);
}
output_format("time_unit", GetTimeUnitString(run.time_unit));
}
else if (run.report_big_o)
{
output_format("cpu_coefficient", run.GetAdjustedCPUTime());
output_format("gpu_coefficient", run.GetAdjustedRealTime());
output_format("big_o", get_complexity(run.complexity));
output_format("time_unit", GetTimeUnitString(run.time_unit));
}
else if (run.report_rms)
{
output_format("rms", run.GetAdjustedCPUTime());
}
for (auto& c : run.counters)
{
if (c.first == "items_per_second")
{
// Report same name as console reporter
output_format("elements_per_second", c.second);
}
else if (c.first == "bytes_per_second")
{
// Report same name as console reporter
output_format("global_mem_bw", c.second);
const double util_bw = calculate_bw_utils(run);
if (util_bw >= 0)
{
output_format("util_bw", util_bw);
}
}
else
{
output_format(c.first, c.second);
}
}
const benchmark::MemoryManager::Result memory_result = run.memory_result;
output_format("allocs_per_iter", run.allocs_per_iter);
output_format("max_bytes_used", memory_result.max_bytes_used);
if (memory_result.total_allocated_bytes != benchmark::MemoryManager::TombstoneValue)
{
output_format("total_allocated_bytes", memory_result.total_allocated_bytes);
}
if (memory_result.net_heap_growth != benchmark::MemoryManager::TombstoneValue)
{
output_format("net_heap_growth", memory_result.net_heap_growth);
}
if (!run.report_label.empty())
{
output_format("label", run.report_label);
}
out << '\n';
}
};
BENCHMARK_DISABLE_DEPRECATED_WARNING
class CustomCSVReporter : public benchmark::CSVReporter
{
private:
bool printed_header_ = false;
std::vector<std::string> elements = {
"name",
"iterations",
"gpu_time",
"cpu_time",
"time_unit",
"global_mem_bw",
"util_bw",
"elements_per_second",
"gpu_noise",
"label",
"error_occurred",
"error_message"};
std::string CsvEscape(const std::string& s)
{
std::string tmp;
tmp.reserve(s.size() + 2);
for (char c : s)
{
switch (c)
{
case '"':
tmp += "\"\"";
break;
default:
tmp += c;
break;
}
}
return '"' + tmp + '"';
}
public:
void PrintHeader(const Run& /*run*/)
{
std::string str = "";
bool first = true;
for (auto element : elements)
{
if (first)
{
first = false;
}
else
{
str += ",";
}
str += element;
}
GetOutputStream() << str << "\n";
}
void PrintRunData(const Run& result)
{
// Report benchmark name
auto& sout = GetOutputStream();
if (result.skipped)
{
sout << std::string(elements.size() - 3, ',');
sout << std::boolalpha << (benchmark::internal::SkippedWithError == result.skipped) << ",";
sout << CsvEscape(result.skip_message) << "\n";
return;
}
sout << CsvEscape(result.benchmark_name()) << ",";
if (!result.report_big_o && !result.report_rms)
{
sout << result.iterations;
}
sout << ",";
sout << result.GetAdjustedRealTime() << ",";
sout << result.GetAdjustedCPUTime() << ",";
if (result.report_big_o)
{
sout << get_complexity(result.complexity);
}
else if (!result.report_rms)
{
sout << benchmark::GetTimeUnitString(result.time_unit);
}
sout << ",";
if (result.counters.find("bytes_per_second") != result.counters.end())
{
sout << result.counters.at("bytes_per_second");
}
sout << ",";
if (result.counters.find("bytes_per_second") != result.counters.end())
{
const double bw_util = calculate_bw_utils(result);
if (bw_util >= 0)
{
sout << bw_util;
}
}
sout << ",";
if (result.counters.find("items_per_second") != result.counters.end())
{
sout << result.counters.at("items_per_second");
}
sout << ",";
if (result.counters.find("gpu_noise") != result.counters.end())
{
sout << result.counters.at("gpu_noise");
}
sout << ",";
if (!result.report_label.empty())
{
sout << CsvEscape(result.report_label);
}
sout << ",,\n";
}
void ReportRuns(const std::vector<Run>& reports)
{
for (const auto& run : reports)
{
// Print the header if none was printed yet
bool print_header = !printed_header_;
if (print_header)
{
printed_header_ = true;
PrintHeader(run);
}
PrintRunData(run);
}
}
};
benchmark::BenchmarkReporter* ChooseCustomReporter()
{
// benchmark::BenchmarkReporter is polymorphic as it has a virtual
// function which allows us to use dynamic_cast to detect the derived type.
using PtrType = benchmark::BenchmarkReporter*;
PtrType default_display_reporter = benchmark::CreateDefaultDisplayReporter();
if (IsType<benchmark::CSVReporter>(default_display_reporter))
{
return PtrType(new CustomCSVReporter);
}
else if (IsType<benchmark::JSONReporter>(default_display_reporter))
{
return PtrType(new CustomJSONReporter);
}
else if (IsType<benchmark::ConsoleReporter>(default_display_reporter))
{
return PtrType(new CustomConsoleReporter);
}
return nullptr;
}
BENCHMARK_RESTORE_DEPRECATED_WARNING
} // namespace bench_utils
#endif // ROCTHRUST_BENCHMARKS_BENCH_UTILS_CUSTOM_REPORTER_HPP_