11 #include "../include/hebench_benchmark_category.h"
12 #include "hebench/modules/general/include/hebench_math_utils.h"
16 namespace TestHarness {
59 return (!h.p && h.size == 0 && h.tag == 0);
95 const std::uint64_t *param_data_pack_indices,
96 const std::vector<hebench::APIBridge::NativeDataBuffer *> &outputs,
99 static constexpr
const std::size_t MaxErrorPrint = 10;
101 std::vector<std::uint64_t> is_valid;
105 if (outputs.size() != dataset->getResultCount())
107 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid number of outputs: 'outputs'."));
111 const std::vector<const hebench::APIBridge::NativeDataBuffer *> &truths =
118 if (!truths.empty() && !outputs.empty() && truths.front())
120 std::size_t index = 0;
121 for (index = 0; retval && index < truths.size(); ++index)
126 if (!outputs.at(index))
128 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Unexpected null output component in: 'outputs[" +
std::to_string(index) +
"]'."));
131 catch (
const std::out_of_range &out_of_range)
133 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Unexpected out of range index output component in: 'outputs[" +
std::to_string(index) +
"]'."));
136 if (outputs.at(index)->size < truths.at(index)->size)
138 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Buffer in outputs is not large enough to contain the expected output: 'outputs[" +
std::to_string(index) +
"]'."));
142 void *p_truth = truths.at(index)->p;
143 void *p_output = outputs.at(index)->p;
149 is_valid = hebench::Utilities::Math::almostEqual(
reinterpret_cast<const std::int32_t *
>(p_truth),
150 reinterpret_cast<const std::int32_t *
>(p_output),
156 is_valid = hebench::Utilities::Math::almostEqual(
reinterpret_cast<const std::int64_t *
>(p_truth),
157 reinterpret_cast<const std::int64_t *
>(p_output),
163 is_valid = hebench::Utilities::Math::almostEqual(
reinterpret_cast<const float *
>(p_truth),
164 reinterpret_cast<const float *
>(p_output),
170 is_valid = hebench::Utilities::Math::almostEqual(
reinterpret_cast<const double *
>(p_truth),
171 reinterpret_cast<const double *
>(p_output),
182 retval = retval && is_valid.empty();
187 std::stringstream ss;
188 ss <<
"Result component, " << (index - 1) << std::endl
189 <<
"Elements not within 1% of each other, " << is_valid.size() << std::endl
190 <<
"Failed indices, ";
191 for (std::size_t i = 0; i < is_valid.size() && i < MaxErrorPrint; ++i)
194 if (i + 1 < is_valid.size() && i + 1 < MaxErrorPrint)
199 if (is_valid.size() > MaxErrorPrint)
203 throw std::runtime_error(ss.str());
212 const std::uint64_t *param_data_pack_indices,
213 const std::vector<hebench::APIBridge::NativeDataBuffer *> &outputs,
216 std::stringstream ss;
220 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid null `dataset`."));
221 if (!param_data_pack_indices)
222 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid null `param_data_pack_indices`."));
223 for (std::size_t param_i = 0; param_i < dataset->getParameterCount(); ++param_i)
225 if (param_data_pack_indices[param_i] >= dataset->getParameterData(param_i).buffer_count)
227 std::stringstream ss;
228 ss <<
"Index out of range `param_data_pack_indices[" << param_i <<
"]` = " << param_data_pack_indices[param_i] <<
". "
229 <<
"Expected less than " << dataset->getParameterData(param_i).buffer_count <<
".";
230 throw std::out_of_range(IL_LOG_MSG_CLASS(ss.str()));
232 if (!dataset->getParameterData(param_i).p_buffers)
234 std::stringstream ss;
235 ss <<
"Invalid empty DataPack buffer in IDataLoader `dataset` for parameter " << param_i <<
".";
236 throw std::invalid_argument(IL_LOG_MSG_CLASS(ss.str()));
240 os <<
"Number of parameters, " << dataset->getParameterCount() << std::endl
241 <<
"Number of result components (expected), " << dataset->getResultCount() << std::endl
242 <<
"Number of result components (received), " << outputs.size() << std::endl
246 const std::vector<const hebench::APIBridge::NativeDataBuffer *> &truths =
251 ss <<
", Parameters, ";
253 os <<
"Parameter index, size" << std::endl;
254 for (std::size_t param_i = 0; param_i < dataset->getParameterCount(); ++param_i)
256 assert(dataset->getParameterData(param_i).param_position == param_i);
264 ss <<
"Ground truth, ";
267 <<
"Ground truth index, size" << std::endl;
268 for (std::size_t result_component_i = 0; result_component_i < truths.size(); ++result_component_i)
270 assert(truths[result_component_i]);
271 os << result_component_i <<
", " << truths[result_component_i]->size /
IDataLoader::sizeOf(data_type) << std::endl;
273 if (result_component_i > 0)
280 <<
"Output index, size" << std::endl;
281 for (std::size_t result_component_i = 0; result_component_i < outputs.size(); ++result_component_i)
283 assert(outputs[result_component_i]);
284 os << result_component_i <<
", " << outputs[result_component_i]->size /
IDataLoader::sizeOf(data_type) << std::endl;
286 if (result_component_i + 1 < outputs.size())
292 << ss.str() << std::endl
296 std::vector<const hebench::APIBridge::NativeDataBuffer *> all_values;
299 for (std::size_t param_i = 0; param_i < dataset->getParameterCount(); ++param_i)
301 all_values.push_back(&dataset->getParameterData(param_i).p_buffers[param_data_pack_indices[param_i]]);
302 os << param_i <<
", ";
305 for (std::size_t result_component_i = 0; result_component_i < truths.size(); ++result_component_i)
307 all_values.push_back(truths[result_component_i]);
308 os << result_component_i <<
", ";
311 for (std::size_t result_component_i = 0; result_component_i < outputs.size(); ++result_component_i)
313 if (result_component_i > 0)
315 all_values.push_back(outputs[result_component_i]);
316 os << result_component_i;
321 data_type,
true,
", ");
Token returned by a successful call to IBenchmarkDescriptor::matchBenchmarkDescriptor().
static std::size_t sizeOf(hebench::APIBridge::DataType data_type)
std::shared_ptr< ResultData > ResultDataPtr
std::shared_ptr< IDataLoader > Ptr
static bool isEmpty(const hebench::APIBridge::Handle &h) noexcept
hebench::APIBridge::ErrorCode destroy()
RAIIHandle & operator=(RAIIHandle &&rhs) noexcept
hebench::APIBridge::Handle handle
virtual bool validateResult(IDataLoader::Ptr dataset, const std::uint64_t *param_data_pack_indices, const std::vector< hebench::APIBridge::NativeDataBuffer * > &outputs, hebench::APIBridge::DataType data_type) const
Validates the result of an operation against the ground truth.
virtual void logResult(std::ostream &os, IDataLoader::Ptr dataset, const std::uint64_t *param_data_pack_indices, const std::vector< hebench::APIBridge::NativeDataBuffer * > &outputs, hebench::APIBridge::DataType data_type) const
Outputs the arguments, expected ground truth, and received result to an output stream.
~PartialBenchmarkCategory() override
PartialBenchmarkCategory(std::shared_ptr< Engine > p_engine, const IBenchmarkDescriptor::DescriptionToken &description_token)
Base class for benchmarks.
const hebench::APIBridge::Handle & handle() const override
@ Float64
64 bits IEEE 754 standard floating point real numbers.
@ Int64
64 bits signed integers.
ErrorCode destroyHandle(Handle h)
Releases resources held by the specified handle.
DataType
Defines data types for a workload.
@ Float32
32 bits IEEE 754 standard floating point real numbers.
@ Int32
32 bits signed integers.
std::uint64_t size
Size of underlying data.
void * p
Pointer to underlying data.
std::int32_t ErrorCode
Return value for API bridge functions.
std::int64_t tag
Optional tag.
Structure to contain flexible data.
std::string to_string(const std::string_view &s)
void printArraysAsColumns(std::ostream &os, const hebench::APIBridge::NativeDataBuffer **p_buffers, std::size_t count, hebench::APIBridge::DataType data_type, bool output_row_index=false, const char *separator=" ")
Writes the collection of NativeDataBuffer as columns to the specified output stream.
#define HEBENCH_ECODE_SUCCESS
Function call succeeded without error.