11 #include "../include/hebench_simple_set_intersection.h"
12 #include "hebench/modules/general/include/hebench_math_utils.h"
15 namespace TestHarness {
35 std::array<std::uint64_t, WorkloadParameterCount> retval;
41 <<
", but " << w_params.size() <<
"received.";
42 throw std::invalid_argument(IL_LOG_MSG_CLASS(ss.str()));
50 ss <<
"Invalid type for workload parameter " << i
51 <<
". Expected type ID " <<
WorkloadParameterType[i] <<
", but " << w_params[i].data_type <<
" received.";
52 throw std::invalid_argument(IL_LOG_MSG_CLASS(ss.str()));
54 else if (w_params[i].u_param <= 0)
57 ss <<
"Invalid number of elements for vector in workload parameter " << i
58 <<
". Expected positive integer, but " << w_params[i].u_param <<
" received.";
59 throw std::invalid_argument(IL_LOG_MSG_CLASS(ss.str()));
62 retval.at(0) = w_params.at(0).u_param;
63 retval.at(1) = w_params.at(1).u_param;
64 retval.at(2) = w_params.at(2).u_param;
87 <<
" |X| -> " << sets_size[0] <<
", "
88 <<
"|Y| -> " << sets_size[1] <<
", "
89 <<
"k -> " << sets_size[2];
97 const std::vector<hebench::APIBridge::WorkloadParam> &w_params)
const
133 void *result,
const void *x,
const void *y,
134 std::uint64_t n, std::uint64_t m, std::uint64_t k);
141 static bool isMemberOf(
const T *dataset,
const T *value, std::uint64_t n, std::uint64_t k)
144 for (
size_t i = 0; !retval && i < n; ++i)
146 std::uint64_t members = 0;
148 for (
size_t j = 0; flag && j < k; ++j)
150 flag = dataset[(i * k) + j] == value[j];
156 retval = members == k;
162 static void mySetIntersection(T *result,
const T *dataset_X,
const T *dataset_Y, std::uint64_t n, std::uint64_t m, std::uint64_t k)
164 size_t idx_result = 0;
167 std::fill(result, result + m * k,
static_cast<T
>(0));
169 for (
size_t idx_x = 0; idx_x < n; ++idx_x)
171 if (isMemberOf(dataset_Y, dataset_X + (idx_x * k), m, k))
174 if (!isMemberOf(result, dataset_X + (idx_x * k), m, k))
176 std::copy(dataset_X + (idx_x * k),
177 dataset_X + (idx_x * k) + k,
178 result + (idx_result * k));
189 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid null `x`"));
191 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid null `y`"));
193 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid null `k`"));
197 mySetIntersection(result, x, y, n, m, k);
201 mySetIntersection(result, y, x, m, n, k);
207 void *result,
const void *x,
const void *y,
208 std::uint64_t n, std::uint64_t m, std::uint64_t k)
212 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Invalid null 'p_result'."));
218 vectorSimpleSetIntersection<std::int32_t>(
reinterpret_cast<std::int32_t *
>(result),
219 reinterpret_cast<const std::int32_t *
>(x),
reinterpret_cast<const std::int32_t *
>(y),
224 vectorSimpleSetIntersection<std::int64_t>(
reinterpret_cast<std::int64_t *
>(result),
225 reinterpret_cast<const std::int64_t *
>(x),
reinterpret_cast<const std::int64_t *
>(y),
230 vectorSimpleSetIntersection<float>(
reinterpret_cast<float *
>(result),
231 reinterpret_cast<const float *
>(x),
reinterpret_cast<const float *
>(y),
236 vectorSimpleSetIntersection<double>(
reinterpret_cast<double *
>(result),
237 reinterpret_cast<const double *
>(x),
reinterpret_cast<const double *
>(y),
242 throw std::invalid_argument(IL_LOG_MSG_CLASS(
"Unknown data type."));
252 std::uint64_t set_size_y,
253 std::uint64_t batch_size_x,
254 std::uint64_t batch_size_y,
255 std::uint64_t element_size_k,
259 retval->init(set_size_x, set_size_y, batch_size_x, batch_size_y, element_size_k, data_type);
264 std::uint64_t set_size_y,
265 std::uint64_t batch_size_x,
266 std::uint64_t batch_size_y,
267 std::uint64_t element_size_k,
269 const std::string &dataset_filename)
272 retval->init(set_size_x, set_size_y, batch_size_x, batch_size_y, element_size_k, data_type, dataset_filename);
276 DataLoader::DataLoader() :
277 m_set_size_x(0), m_set_size_y(0), m_element_size_k(1)
281 void DataLoader::init(std::uint64_t set_size_x,
282 std::uint64_t set_size_y,
283 std::uint64_t batch_size_x,
284 std::uint64_t batch_size_y,
285 std::uint64_t element_size_k,
292 std::size_t batch_sizes[InputDim0 + OutputDim0] = {
295 (batch_size_x * batch_size_y)
298 m_set_size_x = set_size_x;
299 m_set_size_y = set_size_y;
300 m_element_size_k = element_size_k;
303 std::uint64_t sample_set_sizes[InputDim0 + OutputDim0] = {
304 set_size_x * element_size_k,
305 set_size_y * element_size_k,
306 std::min(set_size_x, set_size_y) * element_size_k
311 InputDim0, batch_sizes, sample_set_sizes,
312 OutputDim0, sample_set_sizes + InputDim0,
319 constexpr std::size_t Param_SetX = 0;
320 constexpr std::size_t Param_SetY = 1;
323 for (std::uint64_t sample_i = 0; sample_i < batch_sizes[Param_SetX]; ++sample_i)
327 sample_set_sizes[Param_SetX],
333 for (std::uint64_t sample_i = 0; sample_i < batch_sizes[Param_SetY]; ++sample_i)
336 std::vector<std::uint64_t> indices_x;
337 std::vector<std::uint64_t>::iterator it_indices_y;
338 if (!indices_y.empty())
341 std::sort(indices_y.begin(), indices_y.end());
344 it_indices_y = indices_y.begin();
350 for (std::uint64_t item_y = 0; item_y < set_size_y; ++item_y)
352 std::uint8_t *p_setY_item = p_setY + item_y * element_size_k *
sizeOf(data_type);
353 if (!indices_x.empty() && item_y == *it_indices_y)
356 std::uint8_t *p_setX_item = p_setX + indices_x.back() * element_size_k *
sizeOf(data_type);
357 std::copy(p_setX_item, p_setX_item + element_size_k *
sizeOf(data_type),
359 indices_x.pop_back();
373 for (std::uint64_t sampleX_i = 0; sampleX_i < batch_sizes[Param_SetX]; ++sampleX_i)
374 for (std::uint64_t sampleY_i = 0; sampleY_i < batch_sizes[Param_SetY]; ++sampleY_i)
377 std::uint64_t ppi[] = { sampleX_i, sampleY_i };
385 set_size_x, set_size_y, element_size_k);
391 void DataLoader::init(std::uint64_t set_size_x,
392 std::uint64_t set_size_y,
393 std::uint64_t batch_size_x,
394 std::uint64_t batch_size_y,
395 std::uint64_t element_size_k,
397 const std::string &dataset_filename)
403 std::size_t batch_sizes[InputDim0 + OutputDim0] = {
406 (batch_size_x * batch_size_y)
409 m_set_size_x = set_size_x;
410 m_set_size_y = set_size_y;
411 m_element_size_k = element_size_k;
414 std::uint64_t sample_set_sizes[InputDim0 + OutputDim0] = {
415 set_size_x * element_size_k,
416 set_size_y * element_size_k,
417 std::min(set_size_x, set_size_y) * element_size_k
422 InputDim0, batch_sizes, sample_set_sizes,
423 OutputDim0, sample_set_sizes + InputDim0);
430 const std::uint64_t *param_data_pack_indices,
440 m_set_size_x, m_set_size_y, m_element_size_k);
444 const std::uint64_t *param_data_pack_indices,
445 const std::vector<hebench::APIBridge::NativeDataBuffer *> &outputs,
446 std::uint64_t k_count,
449 static constexpr
const std::size_t MaxErrorPrint = 10;
454 std::vector<std::pair<bool, std::uint64_t>> is_valid;
458 if (outputs.size() != dataset->getResultCount())
460 throw std::invalid_argument(IL_LOG_MSG(
"Invalid number of outputs: 'outputs'."));
464 const std::vector<const hebench::APIBridge::NativeDataBuffer *> &truths =
468 if (!truths.empty() && !outputs.empty() && truths.front())
470 std::size_t index = 0;
471 for (index = 0; retval && index < truths.size(); ++index)
476 if (!outputs.at(index))
478 throw std::invalid_argument(IL_LOG_MSG(
"Unexpected null output component in: 'outputs[" +
std::to_string(index) +
"]'."));
481 catch (
const std::out_of_range &out_of_range)
483 throw std::invalid_argument(IL_LOG_MSG(
"Unexpected out of range index output component in: 'outputs[" +
std::to_string(index) +
"]'."));
486 if (outputs.at(index)->size < truths.at(index)->size)
488 throw std::invalid_argument(IL_LOG_MSG(
"Buffer in outputs is not large enough to contain the expected output: 'outputs[" +
std::to_string(index) +
"]'."));
491 void *p_truth = truths.at(index)->p;
492 void *p_output = outputs.at(index)->p;
501 is_valid =
almostEqualSet(
reinterpret_cast<const std::int32_t *
>(p_truth),
502 reinterpret_cast<const std::int32_t *
>(p_output),
508 is_valid =
almostEqualSet(
reinterpret_cast<const std::int64_t *
>(p_truth),
509 reinterpret_cast<const std::int64_t *
>(p_output),
515 is_valid =
almostEqualSet(
reinterpret_cast<const float *
>(p_truth),
516 reinterpret_cast<const float *
>(p_output),
522 is_valid =
almostEqualSet(
reinterpret_cast<const double *
>(p_truth),
523 reinterpret_cast<const double *
>(p_output),
534 retval = retval && is_valid.empty();
539 std::stringstream ss;
540 ss <<
"Result component, " << (index - 1) << std::endl
541 <<
"Elements mismatched, " << is_valid.size() << std::endl
542 <<
"Failed indices, ";
543 for (std::size_t i = 0; i < is_valid.size() && i < MaxErrorPrint; ++i)
545 ss <<
"(" << (is_valid[i].first ?
"ground truth" :
"output") <<
"; " << is_valid[i].second * k_count <<
".." << is_valid[i].second * k_count + k_count - 1 <<
")";
546 if (i + 1 < is_valid.size() && i + 1 < MaxErrorPrint)
551 if (is_valid.size() > MaxErrorPrint)
555 throw std::runtime_error(ss.str());
const hebench::APIBridge::BenchmarkDescriptor & descriptor
Benchmark backend descriptor, as retrieved by backend, corresponding to the registration handle h_des...
Specifies a benchmark configuration.
std::vector< hebench::APIBridge::WorkloadParam > w_params
Set of arguments for workload parameters.
Static helper class to generate vector data for all supported data types.
static std::vector< std::uint64_t > generateRandomIntersectionIndicesU(std::uint64_t elem_count, std::uint64_t indices_count=0)
Generates uniform random amount of indices.
static std::uint64_t generateRandomIntU(std::uint64_t min_val, std::uint64_t max_val)
static void generateRandomVectorU(hebench::APIBridge::DataType data_type, void *result, std::uint64_t elem_count, double min_val, double max_val)
Generates uniform random data of the specified type.
static std::size_t sizeOf(hebench::APIBridge::DataType data_type)
std::shared_ptr< ResultData > ResultDataPtr
std::shared_ptr< IDataLoader > Ptr
static void completeCategoryParams(hebench::APIBridge::BenchmarkDescriptor &out_descriptor, const hebench::APIBridge::BenchmarkDescriptor &in_descriptor, const BenchmarkDescription::Configuration &config, bool force_config)
Completes common elements of category parameters in a descriptor using the specified configuration.
static bool getForceConfigValues()
Specifies whether frontend will override backend descriptors using configuration data or not.
std::size_t operation_params_count
Number of parameters for the represented workload operation.
std::string workload_name
Human-readable friendly name for the represented workload to be used for its description on the repor...
hebench::APIBridge::BenchmarkDescriptor concrete_descriptor
Benchmark descriptor completed with concrete values assigned to configurable fields.
std::string workload_base_name
Human-readable friendly name for the represented workload to be used for its description on the repor...
Bundles values that need to be filled by a workload during completeWorkloadDescription().
const hebench::APIBridge::DataPack & getResultData(std::uint64_t param_position) const override
Data pack corresponding to the specified component of the result.
const hebench::APIBridge::DataPack & getParameterData(std::uint64_t param_position) const override
Data pack for specified operation parameter (operand).
void init(hebench::APIBridge::DataType data_type, std::size_t input_dim, const std::size_t *input_sample_count_per_dim, const std::uint64_t *input_count_per_dim, std::size_t output_dim, const std::uint64_t *output_count_per_dim, bool allocate_output)
Initializes dimensions of inputs and outputs. No allocation is performed.
std::uint64_t getResultIndex(const std::uint64_t *param_data_pack_indices) const override
Computes the index of the result NativeDataBuffer given the indices of the input data.
void completeWorkloadDescription(WorkloadDescriptionOutput &output, const Engine &engine, const BenchmarkDescription::Backend &backend_desc, const BenchmarkDescription::Configuration &config) const override
Completes the description for the matched benchmark.
static std::array< std::uint64_t, BenchmarkDescriptorCategory::WorkloadParameterCount > fetchSetSize(const std::vector< hebench::APIBridge::WorkloadParam > &w_params)
static constexpr std::uint64_t OpResultCount
static hebench::APIBridge::WorkloadParamType::WorkloadParamType WorkloadParameterType[WorkloadParameterCount]
static constexpr std::uint64_t WorkloadParameterCount
bool matchBenchmarkDescriptor(const hebench::APIBridge::BenchmarkDescriptor &bench_desc, const std::vector< hebench::APIBridge::WorkloadParam > &w_params) const override
Determines if the represented benchmark can perform the workload described by a specified HEBench ben...
static constexpr const char * BaseWorkloadName
static constexpr std::uint64_t OpParameterCount
Static helper class to generate vector data for all supported data types.
static void vectorSimpleSetIntersection(hebench::APIBridge::DataType data_type, void *result, const void *x, const void *y, std::uint64_t n, std::uint64_t m, std::uint64_t k)
void computeResult(std::vector< hebench::APIBridge::NativeDataBuffer * > &result, const std::uint64_t *param_data_pack_indices, hebench::APIBridge::DataType data_type) override
Computes result of the operation on the input data given the of the input sample.
static DataLoader::Ptr create(std::uint64_t set_size_x, std::uint64_t set_size_y, std::uint64_t batch_size_x, std::uint64_t batch_size_y, std::uint64_t element_size_k, hebench::APIBridge::DataType data_type)
std::shared_ptr< DataLoader > Ptr
WorkloadParamType
Defines the possible data types for a workload flexible parameter.
@ Float64
64 bits IEEE 754 standard floating point real numbers.
@ Int64
64 bits signed integers.
@ UInt64
64 bits unsigned integers.
DataType
Defines data types for a workload.
@ Float32
32 bits IEEE 754 standard floating point real numbers.
@ Int32
32 bits signed integers.
void * p
Pointer to underlying data.
Workload workload
Workload for the benchmark.
NativeDataBuffer * p_buffers
Array of data buffers for parameter.
Defines a benchmark test.
std::string to_string(const std::string_view &s)
bool validateResult(IDataLoader::Ptr dataset, const std::uint64_t *param_data_pack_indices, const std::vector< hebench::APIBridge::NativeDataBuffer * > &p_outputs, std::uint64_t k_count, hebench::APIBridge::DataType data_type)
std::enable_if< std::is_integral< T >::value||std::is_floating_point< T >::value, std::vector< std::pair< bool, std::uint64_t > > >::type almostEqualSet(const T *X, const T *Y, std::uint64_t n, std::uint64_t m, std::uint64_t k, double pct=0.05)
Finds whether values in two arrays are within a certain percentage of each other.