HEBench
engine.cpp
Go to the documentation of this file.
1 
2 // Copyright (C) 2021 Intel Corporation
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <algorithm>
6 #include <cassert>
7 #include <new>
8 #include <sstream>
9 
13 
14 namespace hebench {
15 namespace cpp {
16 
17 //------------------
18 // class BaseEngine
19 //------------------
20 
21 const std::string BaseEngine::UnknownErrorMsg = "Unknown Error";
22 hebench::APIBridge::ErrorCode BaseEngine::m_last_error = HEBENCH_ECODE_SUCCESS;
23 std::string BaseEngine::m_s_last_error_description;
24 std::unordered_map<hebench::APIBridge::ErrorCode, std::string> BaseEngine::m_map_error_desc = {
25  { HEBENCH_ECODE_SUCCESS, "Success" },
26  { HEBENCH_ECODE_INVALID_ARGS, "Invalid argument." },
27  { HEBENCH_ECODE_CRITICAL_ERROR, "Critical error." }
28 };
29 
31 {
32  //
33 }
34 
36 {
37  auto it = m_map_error_desc.find(err_code);
38  if (it == m_map_error_desc.end())
39  return UnknownErrorMsg;
40  else
41  return it->second;
42 }
43 
45 {
46  setLastError(value, getErrorDesc(value));
47 }
48 
50  const std::string &err_desc)
51 {
52  m_last_error = value;
53  m_s_last_error_description = err_desc;
54 }
55 
57  const hebench::APIBridge::WorkloadParams *p_w_params) const
58 {
59  std::shared_ptr<BenchmarkDescription> p_bd = matchBenchmark(h_bench_desc);
60  if (!p_bd)
61  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid benchmark descriptor not matched."),
63 
64  return p_bd->getBenchmarkDescription(p_w_params);
65 }
66 
67 void BaseEngine::addBenchmarkDescription(std::shared_ptr<BenchmarkDescription> p_desc)
68 {
69  m_descriptors.push_back(p_desc);
70 }
71 
72 void BaseEngine::addErrorCode(hebench::APIBridge::ErrorCode code, const std::string &description)
73 {
74  if (m_map_error_desc.count(code) > 0)
75  throw HEBenchError(HEBERROR_MSG_CLASS("Error code already specified."),
77  m_map_error_desc[code] = description;
78 }
79 
80 void BaseEngine::addSchemeName(hebench::APIBridge::Scheme scheme, const std::string &name)
81 {
82  if (m_map_scheme_name.count(scheme) > 0)
83  throw HEBenchError(HEBERROR_MSG_CLASS("Scheme already specified."),
85  m_map_scheme_name[scheme] = name;
86 }
87 
88 void BaseEngine::addSecurityName(hebench::APIBridge::Security security, const std::string &name)
89 {
90  if (m_map_security_name.count(security) > 0)
91  throw HEBenchError(HEBERROR_MSG_CLASS("Security type already specified."),
93  m_map_security_name[security] = name;
94 }
95 
96 std::shared_ptr<BenchmarkDescription> BaseEngine::matchBenchmark(hebench::APIBridge::Handle h_desc) const
97 {
98  std::shared_ptr<BenchmarkDescription> p_retval;
99  std::size_t index = (std::size_t)(h_desc.p);
100  if (index < m_descriptors.size() && (h_desc.tag & BenchmarkDescription::tag) != 0)
101  p_retval = m_descriptors.at(index);
102 
103  return p_retval;
104 }
105 
106 void BaseEngine::subscribeBenchmarks(hebench::APIBridge::Handle *p_h_bench_descs, std::uint64_t count) const
107 {
108  if (!p_h_bench_descs)
109  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid null parameter: `p_h_bench_descs`."),
111  if (count != static_cast<std::uint64_t>(m_descriptors.size()))
112  {
113  std::stringstream ss;
114  ss << "Invalid size parameter: `count`. Expected " << m_descriptors.size()
115  << ", but " << count << " received.";
116  throw HEBenchError(HEBERROR_MSG_CLASS(ss.str()),
118  } // end if
119 
120  std::uint64_t min_size = std::min(count, static_cast<std::uint64_t>(m_descriptors.size()));
121  assert(min_size == static_cast<std::uint64_t>(m_descriptors.size()));
122  for (std::size_t i = 0; i < min_size; ++i)
123  {
124  p_h_bench_descs[i].p = (void *)(i);
125  p_h_bench_descs[i].size = sizeof(BenchmarkDescription);
126  p_h_bench_descs[i].tag = m_descriptors[i]->classTag();
127  } // end for
128 }
129 
131 {
132  std::shared_ptr<BenchmarkDescription> p_bd = matchBenchmark(h_bench_desc);
133  if (!p_bd)
134  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid benchmark descriptor not matched."),
136  return p_bd->getWorkloadParameterCount();
137 }
138 
140 {
141  std::shared_ptr<BenchmarkDescription> p_bd = matchBenchmark(h_bench_desc);
142  if (!p_bd)
143  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid benchmark descriptor not matched."),
145  return p_bd->getWorkloadDefaultParameters().size();
146 }
147 
150  hebench::APIBridge::WorkloadParams *p_default_params,
151  std::uint64_t default_count) const
152 {
153  if (!p_bench_desc)
154  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid null parameter: p_bench_desc"),
156 
157  std::shared_ptr<BenchmarkDescription> p_bd = matchBenchmark(h_bench_desc);
158  if (!p_bd)
159  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid benchmark descriptor not matched."),
161 
162  p_bd->getBenchmarkDescriptor(*p_bench_desc);
163 
164  if (p_default_params)
165  {
166  // return the default parameters
167  const auto &default_params = p_bd->getWorkloadDefaultParameters();
168  std::uint64_t min_default_count = std::min<std::uint64_t>(default_count, default_params.size());
169  for (std::size_t i = 0; i < min_default_count; ++i)
170  {
171  // all WorkloadParams elements in p_default_params must be pre-allocated by caller.
172  if (p_default_params[i].count < default_params[i].size())
173  throw HEBenchError(HEBERROR_MSG_CLASS("Insufficient space allocated for default set of parameters: " + std::to_string(i)),
175  std::copy(default_params[i].begin(), default_params[i].end(), p_default_params[i].params);
176  } // end for
177  } // end if
178 }
179 
181  const hebench::APIBridge::WorkloadParams *p_params)
182 {
183  std::shared_ptr<BenchmarkDescription> p_bd = matchBenchmark(h_bench_desc);
184  if (!p_bd)
185  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid benchmark descriptor not matched."),
187 
188  BaseBenchmark *p_bench = p_bd->createBenchmark(*this, p_params);
189  BenchmarkHandle *p_bh = this->template createObj<BenchmarkHandle>();
190  p_bh->p_benchmark = p_bench;
191  p_bh->p_bench_description = p_bd.get();
193  retval.p = p_bh;
194  retval.size = sizeof(BenchmarkHandle);
196  return retval;
197 }
198 
200 {
201  if (h_bench.p)
202  {
203  if ((h_bench.tag & (BaseBenchmark::tag | BenchmarkDescription::tag)) == 0)
204  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid handle not matching benchmark type."),
206 
207  BenchmarkHandle *p_bh = reinterpret_cast<BenchmarkHandle *>(h_bench.p);
208  if (!p_bh->p_benchmark || !p_bh->p_bench_description)
209  throw HEBenchError(HEBERROR_MSG_CLASS("Invalid empty handle."),
211 
213  this->template destroyObj<BenchmarkHandle>(p_bh);
214  } // end if
215 }
216 
217 void BaseEngine::checkHandleTags(hebench::APIBridge::Handle h, std::int64_t check_tags) const
218 {
219  if ((check_tags & ITaggedObject::MaskReservedBits) != 0)
220  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Invalid `check_tags` detected. Most significant 8 bits of tags are reserved."),
223  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Invalid tag detected. Expected EngineObject::tag."),
225  if ((h.tag & check_tags) != check_tags)
226  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Invalid tag detected. Expected " + std::to_string(check_tags) + "."),
228 }
229 
230 hebench::APIBridge::Handle BaseEngine::duplicateHandle(hebench::APIBridge::Handle h, std::int64_t new_tags, std::int64_t check_tags) const
231 {
232  checkHandleTags(h, check_tags);
233  if (new_tags != h.tag && (new_tags & ITaggedObject::MaskReservedBits) != 0)
234  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Invalid `new_tags` detected. Most significant 8 bits of tags are reserved."),
236 
237  return duplicateHandleInternal(h, new_tags);
238 }
239 
241 {
242  checkHandleTags(h, check_tags);
243  return duplicateHandleInternal(h, h.tag);
244 }
245 
246 hebench::APIBridge::Handle BaseEngine::duplicateHandleInternal(hebench::APIBridge::Handle h, std::int64_t new_tag) const
247 {
248  if (!h.p)
249  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Invalid null handle."),
251 
252  // retrieve our internal format object from the handle
253  hebench::cpp::EngineObject *p_obj = reinterpret_cast<hebench::cpp::EngineObject *>(h.p);
254  assert(p_obj);
255  if (this != &p_obj->engine())
256  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Invalid handle. Handle was not created by invoked engine."),
258  // copy internal object
259  hebench::cpp::EngineObject *p_retval = new EngineObject(*p_obj);
260  if (!p_retval)
261  throw hebench::cpp::HEBenchError(HEBERROR_MSG_CLASS("Allocation failed."),
264  retval.p = p_retval;
265  retval.size = h.size;
266  retval.tag = p_retval->classTag() | new_tag;
267  return retval;
268 }
269 
270 } // namespace cpp
271 } // namespace hebench
Top level opaque benchmark class.
Definition: benchmark.hpp:143
std::int64_t classTag() const override
Retrieves the tag of the class to which this object belongs.
Definition: benchmark.hpp:199
static constexpr std::int64_t tag
Used to identify this class when returned as a handle to Test Harness.
Definition: benchmark.hpp:152
std::shared_ptr< BenchmarkDescription > matchBenchmark(hebench::APIBridge::Handle h_desc) const
Retrieves the BenchmarkDescription object pointed by the specified handle.
Definition: engine.cpp:96
static const std::string & getErrorDesc(hebench::APIBridge::ErrorCode err_code)
Retrieves the description of a specific error code.
Definition: engine.cpp:35
std::uint64_t getWorkloadParamsCount(hebench::APIBridge::Handle h_bench_desc) const
Retrieves the number of workload parameters for the decribed benchmark.
Definition: engine.cpp:130
hebench::APIBridge::Handle createBenchmark(hebench::APIBridge::Handle h_bench_desc, const hebench::APIBridge::WorkloadParams *p_params)
Creates the benchmark specified by the descriptor.
Definition: engine.cpp:180
void addBenchmarkDescription(std::shared_ptr< BenchmarkDescription > p_desc)
Adds a new benchmark to the list of benchmarks to register by this backend.
Definition: engine.cpp:67
std::string getBenchmarkDescriptionEx(hebench::APIBridge::Handle h_bench_desc, const hebench::APIBridge::WorkloadParams *p_w_params) const
Retrieves backend specific text description for a benchmark descriptor.
Definition: engine.cpp:56
void destroyBenchmark(hebench::APIBridge::Handle h_bench)
Destroys and cleans up a benchmark created by createBenchmark().
Definition: engine.cpp:199
void subscribeBenchmarks(hebench::APIBridge::Handle *p_h_bench_descs, std::uint64_t count) const
Retrieves the benchmarks for which the backend is registering to perform.
Definition: engine.cpp:106
void addSchemeName(hebench::APIBridge::Scheme scheme, const std::string &name)
Adds a new supported scheme and name pair to the list of schemes supported by this backend.
Definition: engine.cpp:80
hebench::APIBridge::Handle duplicateHandle(hebench::APIBridge::Handle h, std::int64_t new_tag, std::int64_t check_tags) const
Duplicates a handle created by createhandle().
Definition: engine.cpp:230
static void setLastError(hebench::APIBridge::ErrorCode value)
Sets the last error code that occurred.
Definition: engine.cpp:44
std::uint64_t getDefaultWorkloadParamsCount(hebench::APIBridge::Handle h_bench_desc) const
Retrieves the number of sets of default arguments supported by this benchmark's workload.
Definition: engine.cpp:139
static void addErrorCode(hebench::APIBridge::ErrorCode code, const std::string &description)
Adds a new error code and the error description to the list of possible error codes that this backend...
Definition: engine.cpp:72
void describeBenchmark(hebench::APIBridge::Handle h_bench_desc, hebench::APIBridge::BenchmarkDescriptor *p_bench_desc, hebench::APIBridge::WorkloadParams *p_default_params, std::uint64_t default_count) const
Definition: engine.cpp:148
void addSecurityName(hebench::APIBridge::Security security, const std::string &name)
Adds a new supported security and name pair to the list of securitty types supported by this backend.
Definition: engine.cpp:88
Base class for objects representing a specific benchmark based on an HEBench benchmark descriptor.
Definition: benchmark.hpp:36
virtual void destroyBenchmark(BaseBenchmark *p_bench)=0
Destroys and frees resources held by a BaseBenchmark (or derived) object previously created by create...
static constexpr std::int64_t tag
Used to identify this class when returned as a handle to Test Harness.
Definition: benchmark.hpp:42
Helper class to encapsulate objects that will cross the boundary of the API Bridge.
std::int64_t classTag() const override
Retrieves the tag of the class to which this object belongs.
static constexpr std::int64_t tag
Used to identify this class when returned as a handle to Test Harness.
const BaseEngine & engine() const
static constexpr std::int64_t MaskReservedBits
Mask representing all bits reserved by C++ wrapper.
#define HEBERROR_MSG_CLASS(message)
std::int32_t Scheme
Open-ended homomorphic encryption scheme ID.
Definition: types.h:406
std::int32_t Security
Open-ended homomorphic encryption scheme security ID.
Definition: types.h:412
std::uint64_t size
Size of underlying data.
Definition: types.h:564
void * p
Pointer to underlying data.
Definition: types.h:558
std::int32_t ErrorCode
Return value for API bridge functions.
Definition: types.h:34
std::int64_t tag
Optional tag.
Definition: types.h:569
Defines a benchmark test.
Definition: types.h:527
Specifies the parameters for a workload.
Definition: types.h:363
Structure to contain flexible data.
Definition: types.h:552
std::string to_string(const std::string_view &s)
BenchmarkDescription * p_bench_description
Definition: engine.hpp:30
BaseBenchmark * p_benchmark
Definition: engine.hpp:29
Bundles a benchmark and its description to cross the API Bridge as a handle.
Definition: engine.hpp:28
#define HEBENCH_ECODE_SUCCESS
Function call succeeded without error.
Definition: types.h:39
#define HEBENCH_ECODE_INVALID_ARGS
Indicates invalid arguments to function call.
Definition: types.h:42
#define HEBENCH_ECODE_CRITICAL_ERROR
Specifies a critical error.
Definition: types.h:50