16 #include <string_view> 
   17 #include <unordered_map> 
   19 #include <yaml-cpp/yaml.h> 
   21 #include "hebench/modules/general/include/hebench_math_utils.h" 
   22 #include "hebench/modules/general/include/hebench_utilities.h" 
   49     static YAML::Node createWorkloadParamValueYAMLNode(
const T &value)
 
   52         retval[
"from"] = value;
 
   54         retval[
"step"] = 
static_cast<T
>(0); 
 
   64                                                                      std::size_t benchmark_index,
 
   65                                                                      const YAML::Node &yaml_bench,
 
   67                                                                      std::uint64_t fallback_min_test_time,
 
   68                                                                      std::uint64_t fallback_sample_size);
 
   74         return retrieveValue<T>(node.as<std::string>());
 
   78     static std::string getCleanEnvVariableName(std::string s_var_name)
 
   80         s_var_name.erase(0, s_var_name.find_first_not_of(
" \t\n\r\f\v"));
 
   81         s_var_name.erase(s_var_name.find_last_not_of(
" \t\n\r\f\v") + 1);
 
   82         return !s_var_name.empty() && s_var_name.front() == 
'$' ? s_var_name.substr(1) : std::string();
 
   84     static std::string evaluateEnvVariable(
const std::string &s_var_name)
 
   87         if (!s_var_name.empty())
 
   89             const char *c_value = std::getenv(s_var_name.c_str());
 
   97     static std::size_t computeComponentSize(
const YAML::Node &node_from,
 
   98                                             const YAML::Node &node_to,
 
   99                                             const YAML::Node &node_step)
 
  101         T param_step = retrieveValue<T>(node_step);
 
  102         if (param_step == 
static_cast<T
>(0))
 
  103             param_step = std::numeric_limits<T>::max();
 
  104         T tmp_to   = retrieveValue<T>(node_to);
 
  105         T tmp_from = retrieveValue<T>(node_from);
 
  106         if (tmp_to < tmp_from)
 
  108         return static_cast<std::size_t
>((tmp_to - tmp_from) / param_step) + 1;
 
  111     template <
typename T>
 
  112     static T computeParamValue(std::size_t count,
 
  113                                const YAML::Node &node_from,
 
  114                                const YAML::Node &node_step)
 
  116         return static_cast<T
>(count * retrieveValue<T>(node_step) + retrieveValue<T>(node_from));
 
  125 inline std::string ConfigImporterImpl::retrieveValue<std::string>(
const std::string &s_value)
 
  127     std::string s_tmp = getCleanEnvVariableName(s_value);
 
  128     return s_tmp.empty() ? s_value : evaluateEnvVariable(s_tmp);
 
  131 template <
typename T>
 
  135     std::string s_tmp = getCleanEnvVariableName(s_value);
 
  136     std::stringstream ss(s_tmp.empty() ? s_value : evaluateEnvVariable(s_tmp));
 
  140         std::stringstream ss_err;
 
  141         ss_err << 
"ConfigImporterImpl::" << __func__ << 
"():" << __LINE__ << 
": " 
  142                << 
"Invalid conversion for value \"" << s_value << 
"\"";
 
  143         throw std::runtime_error(ss_err.str());
 
  150                                                                               std::size_t benchmark_index,
 
  151                                                                               const YAML::Node &yaml_bench,
 
  153                                                                               std::uint64_t fallback_min_test_time,
 
  154                                                                               std::uint64_t fallback_sample_size)
 
  156     assert(
retrieveValue<decltype(benchmark_index)>(yaml_bench[
"ID"]) == benchmark_index);
 
  158     std::vector<BenchmarkRequest> retval;
 
  160     std::filesystem::path dataset_filename;
 
  161     std::uint64_t default_min_test_time_ms = 0;
 
  162     std::vector<std::uint64_t> default_sample_sizes;
 
  164     if (yaml_bench[
"dataset"].IsDefined() && !yaml_bench[
"dataset"].IsNull())
 
  166         dataset_filename = std::filesystem::path(retrieveValue<std::string>(yaml_bench[
"dataset"]));
 
  167         if (dataset_filename.is_relative())
 
  168             dataset_filename = working_path / dataset_filename;
 
  172             dataset_filename = std::filesystem::canonical(dataset_filename);
 
  174         catch (
const std::exception &ex)
 
  176             YAML::Mark yaml_mark = yaml_bench[
"dataset"].Mark();
 
  177             std::stringstream ss;
 
  179             if (yaml_mark.is_null())
 
  180                 ss << 
"benchmark with ID " << benchmark_index;
 
  182                 ss << 
"line " << yaml_mark.line + 1;
 
  183             ss << 
"." << std::endl
 
  184                << 
"  dataset: \"" << yaml_bench[
"dataset"] << 
"\"" << std::endl
 
  186             throw std::runtime_error(ss.str());
 
  190     if (yaml_bench[
"default_min_test_time"].IsDefined())
 
  191         default_min_test_time_ms = retrieveValue<decltype(default_min_test_time_ms)>(yaml_bench[
"default_min_test_time"]);
 
  193     if (yaml_bench[
"default_sample_sizes"].IsDefined())
 
  195         if (!yaml_bench[
"default_sample_sizes"].IsMap())
 
  197             YAML::Mark yaml_mark = yaml_bench[
"default_sample_sizes"].Mark();
 
  198             std::stringstream ss;
 
  199             ss << 
"Value of field `default_sample_sizes` in ";
 
  200             if (yaml_mark.is_null())
 
  201                 ss << 
"benchmark with ID " << benchmark_index;
 
  203                 ss << 
"line " << yaml_mark.line + 1;
 
  204             ss << 
" must be a map matching operation parameter index to the corresponding sample size.";
 
  205             throw std::runtime_error(ss.str());
 
  207         for (
auto it = yaml_bench[
"default_sample_sizes"].begin(); it != yaml_bench[
"default_sample_sizes"].end(); ++it)
 
  211             std::size_t key = it->first.as<std::size_t>();
 
  212             if (default_sample_sizes.size() <= key)
 
  213                 default_sample_sizes.resize(key + 1, 0);
 
  214             default_sample_sizes[key] = retrieveValue<std::uint64_t>(it->second);
 
  218     if (yaml_bench[
"params"].IsDefined() && yaml_bench[
"params"].size() > 0)
 
  221         std::vector<std::size_t> component_sizes(yaml_bench[
"params"].size());
 
  222         for (std::size_t param_i = 0; param_i < component_sizes.size(); ++param_i)
 
  226             if (!yaml_bench[
"params"][param_i].IsDefined())
 
  228                 std::stringstream ss;
 
  229                 ss << 
"workload parameter index " << param_i << 
" not found in benchmark with ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  230                 throw std::runtime_error(ss.str());
 
  232             if (!yaml_bench[
"params"][param_i][
"name"].IsDefined())
 
  234                 std::stringstream ss;
 
  235                 ss << 
"Field \"name\" not found for workload parameter index " << param_i << 
", benchmark ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  236                 throw std::runtime_error(ss.str());
 
  238             if (!yaml_bench[
"params"][param_i][
"type"].IsDefined())
 
  240                 std::stringstream ss;
 
  241                 ss << 
"Field \"type\" not found for workload parameter index " << param_i << 
", benchmark ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  242                 throw std::runtime_error(ss.str());
 
  244             if (!yaml_bench[
"params"][param_i][
"value"].IsDefined())
 
  246                 std::stringstream ss;
 
  247                 ss << 
"Field \"value\" not found for workload parameter index " << param_i << 
", benchmark ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  248                 throw std::runtime_error(ss.str());
 
  251             YAML::Node yaml_param_value = yaml_bench[
"params"][param_i][
"value"];
 
  252             if (!yaml_param_value[
"from"].IsDefined())
 
  254                 std::stringstream ss;
 
  255                 ss << 
"Field \"from\" not found for \"value\" in workload parameter index " << param_i << 
", benchmark ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  256                 throw std::runtime_error(ss.str());
 
  258             if (!yaml_param_value[
"to"].IsDefined())
 
  260                 std::stringstream ss;
 
  261                 ss << 
"Field \"to\" not found for \"value\" in workload parameter index " << param_i << 
", benchmark ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  262                 throw std::runtime_error(ss.str());
 
  264             if (!yaml_param_value[
"step"].IsDefined())
 
  266                 std::stringstream ss;
 
  267                 ss << 
"Field \"step\" not found for \"value\" in workload parameter index " << param_i << 
", benchmark ID " << benchmark_index << 
", defined at line " << yaml_bench.Mark().line + 1 << 
".";
 
  268                 throw std::runtime_error(ss.str());
 
  272             std::string param_type = hebench::Utilities::ToLowerCase(retrieveValue<std::string>(yaml_bench[
"params"][param_i][
"type"]));
 
  273             if (param_type == 
"uint64")
 
  275                 component_sizes[param_i] =
 
  276                     computeComponentSize<std::uint64_t>(yaml_param_value[
"from"],
 
  277                                                         yaml_param_value[
"to"],
 
  278                                                         yaml_param_value[
"step"]);
 
  280             else if (param_type == 
"int64")
 
  282                 component_sizes[param_i] =
 
  283                     computeComponentSize<std::int64_t>(yaml_param_value[
"from"],
 
  284                                                        yaml_param_value[
"to"],
 
  285                                                        yaml_param_value[
"step"]);
 
  287             else if (param_type == 
"float64")
 
  289                 component_sizes[param_i] =
 
  290                     computeComponentSize<double>(yaml_param_value[
"from"],
 
  291                                                  yaml_param_value[
"to"],
 
  292                                                  yaml_param_value[
"step"]);
 
  296                 std::stringstream ss;
 
  297                 ss << 
"Invalid \"type\" found in parameter index " << param_i
 
  298                    << 
", benchmark ID " << benchmark_index << 
": " 
  299                    << yaml_bench[
"params"][param_i][
"type"].as<std::string>() << 
".";
 
  300                 throw std::runtime_error(ss.str());
 
  304         hebench::Utilities::Math::ComponentCounter c_counter(component_sizes);
 
  308             const std::vector<std::size_t> &count = c_counter.getCount();
 
  311             config.
default_min_test_time_ms     = default_min_test_time_ms <= 0 ? fallback_min_test_time : default_min_test_time_ms;
 
  314             for (std::size_t param_i = 0; param_i < count.size(); ++param_i)
 
  318                 YAML::Node yaml_param       = yaml_bench[
"params"][param_i];
 
  319                 YAML::Node yaml_param_value = yaml_param[
"value"];
 
  320                 std::string param_type      = hebench::Utilities::ToLowerCase(retrieveValue<std::string>(yaml_param[
"type"]));
 
  322                 if (param_type == 
"uint64")
 
  325                     w_param.u_param   = computeParamValue<decltype(w_param.u_param)>(count[param_i],
 
  326                                                                                    yaml_param_value[
"from"],
 
  327                                                                                    yaml_param_value[
"step"]);
 
  329                 else if (param_type == 
"int64")
 
  332                     w_param.i_param   = computeParamValue<decltype(w_param.i_param)>(count[param_i],
 
  333                                                                                    yaml_param_value[
"from"],
 
  334                                                                                    yaml_param_value[
"step"]);
 
  336                 else if (param_type == 
"float64")
 
  339                     w_param.f_param   = computeParamValue<decltype(w_param.f_param)>(count[param_i],
 
  340                                                                                    yaml_param_value[
"from"],
 
  341                                                                                    yaml_param_value[
"step"]);
 
  352                     throw std::runtime_error(
"External dataset is only supported on benchmark configuration blocks that define a single benchmark " 
  353                                              "(for a workload parameter, fields `from` and `to` must match).");
 
  357                     throw std::runtime_error(
"Unable to match benchmark: no match found able to support selected benchmark with specified workload parameters.");
 
  358                 retval.emplace_back();
 
  359                 retval.back().index         = benchmark_index;
 
  360                 retval.back().configuration = p_token->getBenchmarkConfiguration();
 
  362             catch (std::runtime_error &ex)
 
  364                 std::stringstream ss;
 
  365                 ss << 
"Benchmark ID: " << benchmark_index << std::endl
 
  367                 throw std::runtime_error(ss.str());
 
  369         } 
while (!c_counter.inc()); 
 
  376             retval.emplace_back();
 
  377             retval.back().configuration.default_min_test_time_ms = default_min_test_time_ms;
 
  378             retval.back().configuration.default_sample_sizes     = default_sample_sizes;
 
  382                 throw std::runtime_error(
"Unable to match benchmark.");
 
  383             retval.back().index         = benchmark_index;
 
  384             retval.back().configuration = p_token->getBenchmarkConfiguration();
 
  386         catch (std::runtime_error &ex)
 
  388             std::stringstream ss;
 
  389             ss << 
"Benchmark ID: " << benchmark_index << std::endl
 
  391             throw std::runtime_error(ss.str());
 
  405     retval[
"name"] = w_param.
name;
 
  409         retval[
"type"]  = 
"Int64";
 
  410         retval[
"value"] = createWorkloadParamValueYAMLNode<decltype(w_param.i_param)>(w_param.i_param);
 
  414         retval[
"type"]  = 
"UInt64";
 
  415         retval[
"value"] = createWorkloadParamValueYAMLNode<decltype(w_param.u_param)>(w_param.u_param);
 
  419         retval[
"type"]  = 
"Float64";
 
  420         retval[
"value"] = createWorkloadParamValueYAMLNode<decltype(w_param.f_param)>(w_param.f_param);
 
  424         throw std::invalid_argument(
"Invalid data type detected in 'w_param'.");
 
  436     std::stringstream ss;
 
  438     ss << 
"Section \"description\" is for informational purposes only. It shows the" << std::endl
 
  439        << 
"benchmark descriptor matching the benchmark ID. Changing contents of" << std::endl
 
  440        << 
"\"description\" has no effect.";
 
  441     out << YAML::Newline;
 
  442     out << YAML::Comment(ss.str());
 
  444     YAML::Node node_benchmark;
 
  445     YAML::Node node_bench_description;
 
  446     node_bench_description[
"workload"]      = description.
workload;
 
  447     node_bench_description[
"workload_name"] = description.
workload_name;
 
  448     node_bench_description[
"data_type"]     = description.
data_type;
 
  449     node_bench_description[
"category"]      = description.
category;
 
  450     node_bench_description[
"scheme"]        = description.
scheme;
 
  451     node_bench_description[
"security"]      = description.
security;
 
  452     node_bench_description[
"cipher_flags"]  = description.
cipher_flags;
 
  453     node_bench_description[
"other"]         = description.
other;
 
  454     node_bench_description[
"notes"]         = YAML::Node(YAML::NodeType::Null);
 
  455     node_benchmark[
"ID"]                    = bench_req.
index;
 
  456     node_benchmark[
"description"]           = node_bench_description;
 
  457     node_benchmark[
"dataset"]               = YAML::Node(YAML::NodeType::Null);
 
  463         node_benchmark[
"default_sample_sizes"][
"to_map"] = 
"yes"; 
 
  464         node_benchmark[
"default_sample_sizes"].remove(
"to_map");
 
  468         for (std::size_t param_i = 0; param_i < config.
w_params.size(); ++param_i)
 
  469             node_benchmark[
"params"].push_back(createWorkloadParamYAMLNode(config.
w_params[param_i]));
 
  470         node_benchmark[
"params"][
"to_map"] = 
"yes"; 
 
  471         node_benchmark[
"params"].remove(
"to_map");
 
  473     out << node_benchmark << YAML::Newline;
 
  481                                                                      std::uint64_t fallback_random_seed)
 
  483     std::shared_ptr<BenchmarkConfigLoader> p_retval =
 
  484         std::shared_ptr<BenchmarkConfigLoader>(
new BenchmarkConfigLoader(yaml_filename, fallback_random_seed));
 
  489                                              std::uint64_t fallback_random_seed) :
 
  490     m_random_seed(fallback_random_seed),
 
  491     m_default_min_test_time_ms(0),
 
  492     m_default_sample_size(0)
 
  495     m_filename                     = std::filesystem::canonical(yaml_filename).string();
 
  496     std::filesystem::path file_dir = std::filesystem::path(m_filename).remove_filename();
 
  497     YAML::Node root                = YAML::LoadFile(m_filename);
 
  499     if (!root[
"benchmark"].IsDefined())
 
  500         throw std::runtime_error(
"Map \"benchmark\" not found at root of configuration file.");
 
  501     if (!root[
"benchmark"].IsSequence())
 
  502         throw std::runtime_error(
"Value for map \"benchmark\" is not a valid YAML sequence.");
 
  505     if (root[
"default_min_test_time"].IsDefined())
 
  506         m_default_min_test_time_ms =
 
  507             ConfigImporterImpl::retrieveValue<decltype(m_default_min_test_time_ms)>(root[
"default_min_test_time"]);
 
  508     if (root[
"default_sample_size"].IsDefined())
 
  509         m_default_sample_size =
 
  510             ConfigImporterImpl::retrieveValue<decltype(m_default_sample_size)>(root[
"default_sample_size"]);
 
  511     if (root[
"random_seed"].IsDefined())
 
  512         m_random_seed = ConfigImporterImpl::retrieveValue<std::uint64_t>(root[
"random_seed"]);
 
  514     if (root[
"initialization_data"].IsDefined() && !root[
"initialization_data"].IsNull())
 
  517         std::string init_data = ConfigImporterImpl::retrieveValue<std::string>(root[
"initialization_data"]);
 
  518         if (!init_data.empty())
 
  520             std::filesystem::path init_data_filepath = init_data;
 
  522             if (init_data_filepath.is_relative())
 
  524                 init_data_filepath = file_dir / init_data_filepath;
 
  525             if (std::filesystem::exists(init_data_filepath) && std::filesystem::is_regular_file(init_data_filepath))
 
  528                 fnum.open(init_data_filepath, std::ifstream::in | std::ifstream::binary);
 
  531                     std::stringstream ss;
 
  532                     ss << 
"Could not open file " << init_data_filepath
 
  533                        << 
" for reading as indicated by field `initialization_data`.";
 
  534                     throw std::runtime_error(ss.str());
 
  537                 fnum.seekg(0, fnum.end);
 
  538                 m_data.resize(fnum.tellg());
 
  539                 fnum.seekg(0, fnum.beg);
 
  540                 fnum.read(
reinterpret_cast<std::ifstream::char_type *
>(m_data.data()), m_data.size());
 
  544                 m_data.assign(init_data.begin(), init_data.end());
 
  548     m_yaml_content = std::shared_ptr<YAML::Node>(
new YAML::Node(root));
 
  556                                              std::uint64_t random_seed,
 
  557                                              const std::string s_backend) :
 
  558     m_wp_engine(wp_engine),
 
  559     m_s_backend(s_backend)
 
  561     std::shared_ptr<hebench::TestHarness::Engine> p_engine = wp_engine.lock();
 
  563         throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid empty 'wp_engine'."));
 
  565     std::size_t count_benchmarks                      = p_engine->countBenchmarks();
 
  567     std::vector<BenchmarkRequest> &benchmark_requests = m_default_benchmarks.
benchmark_requests;
 
  568     benchmark_requests.reserve(count_benchmarks);
 
  569     for (std::size_t bench_i = 0; bench_i < count_benchmarks; ++bench_i)
 
  571         std::vector<std::vector<hebench::APIBridge::WorkloadParam>> w_params_set =
 
  572             p_engine->getDefaultWorkloadParams(bench_i);
 
  573         for (std::size_t w_params_i = 0; w_params_i < w_params_set.size(); ++w_params_i)
 
  575             benchmark_requests.emplace_back();
 
  580                 p_engine->describeBenchmark(bench_i, bench_description.
configuration);
 
  582                 throw std::runtime_error(IL_LOG_MSG_CLASS(
"Unexpected error: no matching benchmark found for backend request."));
 
  584             bench_description.
index         = bench_i;
 
  585             bench_description.
configuration = p_token->getBenchmarkConfiguration();
 
  593     std::shared_ptr<hebench::TestHarness::Engine> p_engine = m_wp_engine.lock();
 
  595         throw std::logic_error(IL_LOG_MSG_CLASS(
"Invalid internal state: engine object has been released."));
 
  597     std::filesystem::path path_backend = m_s_backend;
 
  601     std::stringstream ss;
 
  602     ss << 
"HEBench auto-generated benchmark selection and configuration file." << std::endl
 
  604     if (path_backend.has_filename())
 
  605         ss << 
"Generated from backend: " << std::endl
 
  606            << 
"  " << path_backend.filename() << std::endl
 
  608     ss << 
"Only benchmarks with their workload parameters specified here will run when" << std::endl
 
  609        << 
"this configuration file is used with Test Harness. This configuration only" << std::endl
 
  610        << 
"works for the backend used to generate this file (the backend)." << std::endl
 
  612        << 
"Benchmark \"ID\" represents workload and benchmark descriptor options for the" << std::endl
 
  613        << 
"backend. Benchmark \"params\" are the configurable workload parameters." << std::endl
 
  615        << 
"To use this file do any of the following:" << std::endl
 
  616        << 
"  - Add or remove benchmarks based on pre-existing configurations." << std::endl
 
  617        << 
"  - Modify the configuration and workload parameters for existing or added" << std::endl
 
  618        << 
"    benchmarks." << std::endl
 
  620        << 
"Global configuration values, if present, are used when local values are not" << std::endl
 
  621        << 
"specified per benchmark." << std::endl
 
  623        << 
"When adding new benchmarks:" << std::endl
 
  624        << 
"  The only benchmark IDs supported are those already existing in this" << std::endl
 
  625        << 
"  auto-generated file as reported by the backend. Any new benchmark added" << std::endl
 
  626        << 
"  must have the same number of workload parameters as those already existing" << std::endl
 
  627        << 
"  in this auto-generated file with the same benchmark ID." << std::endl
 
  629        << 
"When modifying workload parameters:" << std::endl
 
  630        << 
"  Number of workload parameters, their type and name must match those of any" << std::endl
 
  631        << 
"  auto-generated benchmark with the same ID." << std::endl
 
  632        << 
"  Refer to workload and backend specifications for supported range of values" << std::endl
 
  633        << 
"  for each workload parameter. Invalid values will cause the benchmark to" << std::endl
 
  634        << 
"  fail during execution." << std::endl
 
  636        << 
"If non-null \"dataset\" is specified for a benchmark, the framework will" << std::endl
 
  637        << 
"attempt to load the specified file and use its contents as values for inputs" << std::endl
 
  638        << 
"and ground truths instead of using synthetic data. For a benchmark" << std::endl
 
  639        << 
"description specifying a dataset file, all workload parameter ranges must" << std::endl
 
  640        << 
"resolve to single values." << std::endl;
 
  642     out << YAML::Comment(ss.str()) << YAML::Newline;
 
  645     out << YAML::Newline;
 
  647     out << YAML::BeginMap;
 
  649     ss = std::stringstream();
 
  650     ss << 
"Default minimum test time in milliseconds. Latency tests specifying" << std::endl
 
  651        << 
"default test time and Offline tests will be repeated until this time" << std::endl
 
  652        << 
"has elapsed. Defaults to 0 if not present (Latency executes twice," << std::endl
 
  653        << 
"Offline executes once).";
 
  654     out << YAML::Comment(ss.str())
 
  655         << YAML::Key << 
"default_min_test_time" << YAML::Value << 0;
 
  656     out << YAML::Newline << YAML::Newline;
 
  658     ss = std::stringstream();
 
  659     ss << 
"Default sample size to use for operation parameters that support" << std::endl
 
  660        << 
"variable sample size in Offline category. Defaults to benchmark" << std::endl
 
  661        << 
"specific if not present.";
 
  662     out << YAML::Comment(ss.str())
 
  663         << YAML::Key << 
"default_sample_size" << YAML::Value << 0;
 
  664     out << YAML::Newline << YAML::Newline;
 
  666     ss = std::stringstream();
 
  667     ss << 
"Random seed to use when generating synthetic data for these benchmarks." << std::endl
 
  668        << 
"Type: unsigned int. Defaults to system time when not present.";
 
  669     out << YAML::Comment(ss.str())
 
  670         << YAML::Key << 
"random_seed" << YAML::Value << bench_configs.
random_seed;
 
  671     out << YAML::Newline << YAML::Newline;
 
  673     ss = std::stringstream();
 
  674     ss << 
"Optional backend initialization data." << std::endl
 
  675        << 
"Type: string (can be null)." << std::endl
 
  676        << 
"When present, if this is the name of an existing file (relative to this" << std::endl
 
  677        << 
"file, or absolute), the file binary contents will be forwarded to the" << std::endl
 
  678        << 
"backend engine during initialization. Otherwise, the specified string is" << std::endl
 
  679        << 
"forwarded as is (without null terminator)";
 
  680     out << YAML::Comment(ss.str())
 
  681         << YAML::Key << 
"initialization_data" << YAML::Value << YAML::Null;
 
  682     out << YAML::Newline << YAML::Newline;
 
  688     out << YAML::BeginMap;
 
  689     out << YAML::Key << 
"benchmark" << YAML::Value
 
  694     for (std::size_t i = 0; i < bench_requests.size(); ++i)
 
  697             p_engine->describeBenchmark(bench_requests[i].index, bench_requests[i].configuration);
 
  700             ss = std::stringstream();
 
  701             ss << 
"No matching benchmark found for backend request " << i
 
  702                << 
" for backend benchmark index " << bench_requests[i].index << 
".";
 
  703             throw std::invalid_argument(IL_LOG_MSG_CLASS(ss.str()));
 
  706         bench_request_corrected.
index                                  = bench_requests[i].index;
 
  707         bench_request_corrected.
configuration                          = p_token->getBenchmarkConfiguration();
 
  716             sample_sizes.clear();
 
  719             for (std::size_t i = 0; i < sample_sizes.size(); ++i)
 
  720                 sample_sizes[i] = p_token->getBackendDescription().descriptor.cat_params.offline.data_count[i];
 
  731     hebench::Utilities::writeToFile(
 
  733         [&out](std::ostream &os) {
 
  742     std::uint64_t default_min_test_time_ms = 0;
 
  743     std::uint64_t default_sample_size      = 0;
 
  747         throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid loader: internal YAML content is not initialized."));
 
  748     std::shared_ptr<hebench::TestHarness::Engine> p_engine = m_wp_engine.lock();
 
  750         throw std::logic_error(IL_LOG_MSG_CLASS(
"Invalid internal state: engine object has been released."));
 
  752     std::filesystem::path file_dir = std::filesystem::path(loader.
getFilename()).remove_filename();
 
  753     YAML::Node root                = *
reinterpret_cast<const YAML::Node *
>(p_yaml_content);
 
  757     root                                              = root[
"benchmark"];
 
  759     benchmark_requests.reserve(root.size());
 
  760     for (std::size_t i = 0; i < root.size(); ++i)
 
  762         if (!root[i][
"ID"].IsDefined())
 
  763             throw std::runtime_error(
"Field \"ID\" not found in benchmark.");
 
  764         std::size_t benchmark_index = ConfigImporterImpl::retrieveValue<std::size_t>(root[i][
"ID"]);
 
  765         std::vector<BenchmarkRequest> node_requests =
 
  770                                                             default_min_test_time_ms,
 
  771                                                             default_sample_size);
 
  772         benchmark_requests.insert(benchmark_requests.end(), node_requests.begin(), node_requests.end());
 
Specifies a benchmark configuration.
std::uint64_t fallback_default_sample_size
Default sample size to be used if a specific size is not specified in the default_sample_sizes collec...
std::vector< std::uint64_t > default_sample_sizes
Default sample size for each operation parameter.
std::vector< hebench::APIBridge::WorkloadParam > w_params
Set of arguments for workload parameters.
std::string dataset_filename
File containing data for the benchmark. If empty string, benchmarks that can auto generate the datase...
std::uint64_t default_min_test_time_ms
Default minimum test time in milliseconds.
IBenchmarkDescriptor::DescriptionToken::Ptr describeBenchmark(std::size_t index, const BenchmarkDescription::Configuration &config) const
Describes a benchmark workload that matches the specified description from the benchmarks registered ...
std::shared_ptr< DescriptionToken > Ptr
BenchmarkSession importConfiguration(const BenchmarkConfigLoader &loader) const
Imports a benchmark configuration from a configurator loader.
BenchmarkConfigBroker(std::weak_ptr< hebench::TestHarness::Engine > wp_engine, std::uint64_t random_seed=0, const std::string s_backend=std::string())
void exportConfiguration(const std::string &yaml_filename, const BenchmarkSession &bench_configs) const
const std::string & getFilename() const
Retrieves the file name used to load the yaml data.
static std::shared_ptr< BenchmarkConfigLoader > create(const std::string &yaml_filename, std::uint64_t fallback_random_seed)
Loads a benchmark configuration from yaml data contained in a file.
BenchmarkConfigLoader(const BenchmarkConfigLoader &)=delete
const void * getYAMLContent(const FriendKey &) const
std::uint64_t getRandomSeed() const
Retrieves the configuration random seed.
const std::vector< std::int8_t > & getInitData() const
static void exportBenchmarkRequest2YAML(YAML::Emitter &out, const BenchmarkRequest &bench_req, const hebench::TestHarness::BenchmarkDescription::Description &description)
exportBenchmarkDescription2YAML
static T retrieveValue(const YAML::Node &node)
static T retrieveValue(const std::string &s_value)
static std::vector< BenchmarkRequest > importYAML2BenchmarkRequest(const std::filesystem::path &working_path, std::size_t benchmark_index, const YAML::Node &yaml_bench, const hebench::TestHarness::Engine &engine, std::uint64_t fallback_min_test_time, std::uint64_t fallback_sample_size)
@ Float64
64 bits IEEE 754 standard floating point real numbers.
@ Int64
64 bits signed integers.
@ UInt64
64 bits unsigned integers.
char name[HEBENCH_MAX_BUFFER_SIZE]
Null-terminated string containing the name for the parameter.
WorkloadParamType::WorkloadParamType data_type
Type of the parameter data.
Category
Defines all possible categories for each workload.
Defines a single workload parameter.
std::string other
Other value used to uniquely identify benchmark implementations.
std::string scheme
Human-readable friendly name of the benchmark scheme.
std::string cipher_flags
Human-readable friendly name of the benchmark cipher parameters.
std::int64_t workload
Workload ID as given by hebench::APIBridge::Workload.
std::string workload_name
Human-readable friendly name of the benchmark workload.
std::string category
Human-readable friendly name of the benchmark category.
std::string data_type
Human-readable friendly name of the benchmark input/output data type.
std::string security
Human-readable friendly name of the benchmark security.
std::vector< BenchmarkRequest > benchmark_requests
hebench::TestHarness::BenchmarkDescription::Configuration configuration
std::uint64_t random_seed
std::vector< std::int8_t > data
std::uint64_t copyString(char *dst, std::uint64_t size, const std::string &src)
Copies a C++ string object into a C-style string.
#define HEBENCH_MAX_BUFFER_SIZE
#define HEBENCH_MAX_OP_PARAMS
Maximum number of parameters supported by an operation.