25 TutorialEltwiseAddBenchmarkDescription::TutorialEltwiseAddBenchmarkDescription()
45 m_descriptor.cat_params.offline.data_count[0] = 2;
46 m_descriptor.cat_params.offline.data_count[1] = 5;
50 m_descriptor.cipher_param_mask = 1 << 1;
59 m_descriptor.security = TUTORIAL_HE_SECURITY_128;
63 m_descriptor.other = 0;
72 default_workload_params.
n() = 400;
73 this->addDefaultParameters(default_workload_params);
78 TutorialEltwiseAddBenchmarkDescription::~TutorialEltwiseAddBenchmarkDescription()
87 ss << BenchmarkDescription::getBenchmarkDescription(p_w_params);
88 ss <<
", Encryption parameters" << std::endl
89 <<
", , HE Library, Microsoft SEAL 3.6" << std::endl
90 <<
", , Poly modulus degree, " << PolyModulusDegree << std::endl
91 <<
", , Coefficient Moduli, 60, 60";
96 <<
", Workload parameters" << std::endl
97 <<
", , n, " << w_params.n();
111 TutorialEngine &ex_engine =
dynamic_cast<TutorialEngine &
>(engine);
112 return new TutorialEltwiseAddBenchmark(ex_engine, m_descriptor, *p_params);
129 TutorialEltwiseAddBenchmark::Workload::SealBFVContext::SealBFVContext(
int poly_modulus_degree)
131 assert(TutorialEltwiseAddBenchmarkDescription::NumCoefficientModuli == 1);
133 seal::EncryptionParameters parms{ seal::scheme_type::bfv };
134 parms.set_poly_modulus_degree(poly_modulus_degree);
135 parms.set_coeff_modulus(seal::CoeffModulus::Create(poly_modulus_degree, { 60, 60 }));
136 parms.set_plain_modulus(seal::PlainModulus::Batching(poly_modulus_degree, 20));
137 m_p_seal_context.reset(
new seal::SEALContext(parms,
true, seal::sec_level_type::tc128));
138 m_p_keygen = std::make_unique<seal::KeyGenerator>(context());
140 m_p_keygen->create_public_key(m_public_key);
141 m_secret_key = m_p_keygen->secret_key();
143 m_p_encryptor = std::make_unique<seal::Encryptor>(context(), m_public_key);
144 m_p_evaluator = std::make_unique<seal::Evaluator>(context());
145 m_p_decryptor = std::make_unique<seal::Decryptor>(context(), m_secret_key);
146 m_p_batch_encoder = std::make_unique<seal::BatchEncoder>(context());
151 if (vector_size <= 0)
152 throw std::invalid_argument(
"vector_size");
153 m_vector_size = vector_size;
154 m_p_context = std::make_shared<SealBFVContext>(TutorialEltwiseAddBenchmarkDescription::PolyModulusDegree);
157 std::vector<seal::Plaintext> TutorialEltwiseAddBenchmark::Workload::encodeVector(
const std::vector<std::vector<std::int64_t>> &vec)
159 std::vector<gsl::span<const std::int64_t>> vec_span(vec.begin(), vec.end());
160 return encodeVector(vec_span);
163 std::vector<seal::Plaintext> TutorialEltwiseAddBenchmark::Workload::encodeVector(
const std::vector<gsl::span<const std::int64_t>> &vec)
165 std::vector<seal::Plaintext> retval(vec.size());
167 for (std::size_t i = 0; i < vec.size(); ++i)
169 assert(vec[i].size() <= context().encoder().slot_count());
170 context().encoder().encode(vec[i], retval[i]);
175 std::vector<seal::Ciphertext> TutorialEltwiseAddBenchmark::Workload::encryptVector(
const std::vector<seal::Plaintext> &encoded_vec)
177 std::vector<seal::Ciphertext> retval(encoded_vec.size());
178 for (std::size_t i = 0; i < encoded_vec.size(); i++)
179 context().encryptor().encrypt(encoded_vec[i], retval[i]);
183 std::vector<seal::Ciphertext> TutorialEltwiseAddBenchmark::Workload::eltwiseadd(
const std::vector<seal::Plaintext> &A,
184 const std::vector<seal::Ciphertext> &B)
186 std::vector<seal::Ciphertext> retval(A.size() * B.size());
187 for (std::size_t A_i = 0; A_i < A.size(); ++A_i)
188 for (std::size_t B_i = 0; B_i < B.size(); ++B_i)
190 seal::Ciphertext &retval_item = retval[A_i * B.size() + B_i];
191 context().evaluator().add_plain(B[B_i], A[A_i], retval_item);
197 std::vector<seal::Plaintext> TutorialEltwiseAddBenchmark::Workload::decryptResult(
const std::vector<seal::Ciphertext> &encrypted_result)
199 std::vector<seal::Plaintext> retval(encrypted_result.size());
200 for (std::size_t i = 0; i < encrypted_result.size(); i++)
201 context().decryptor().decrypt(encrypted_result[i], retval[i]);
205 std::vector<std::vector<int64_t>> TutorialEltwiseAddBenchmark::Workload::decodeResult(
const std::vector<seal::Plaintext> &encoded_result)
207 std::vector<std::vector<int64_t>> retval(encoded_result.size());
208 for (std::size_t i = 0; i < encoded_result.size(); ++i)
210 context().encoder().decode(encoded_result[i], retval[i]);
211 retval[i].resize(m_vector_size);
225 hebench::cpp::BaseBenchmark(engine, bench_desc, bench_params)
230 if (bench_params.
count < TutorialEltwiseAddBenchmarkDescription::NumWorkloadParams)
232 +
std::to_string(TutorialEltwiseAddBenchmarkDescription::NumWorkloadParams)
238 if (w_params.n() <= 0
239 || w_params.n() - 1 > TutorialEltwiseAddBenchmarkDescription::PolyModulusDegree / 2)
241 +
std::to_string(TutorialEltwiseAddBenchmarkDescription::PolyModulusDegree / 2)),
247 m_p_workload = std::make_shared<Workload>(w_params.n());
252 TutorialEltwiseAddBenchmark::~TutorialEltwiseAddBenchmark()
254 m_p_workload.reset();
270 std::stringstream ss;
271 ss <<
"Unexpected number of input samples for operation parameter " << param_pack.
param_position
272 <<
". Expected " << this->getDescriptor().cat_params.offline.data_count[param_pack.
param_position]
280 std::vector<gsl::span<const std::int64_t>> clear_param(param_pack.
buffer_count);
281 for (std::size_t sample_i = 0; sample_i < clear_param.size(); ++sample_i)
284 clear_param[sample_i] =
285 gsl::span<const std::int64_t>(
reinterpret_cast<const std::int64_t *
>(native_sample.
p),
286 native_sample.
size /
sizeof(std::int64_t));
287 assert(clear_param[sample_i].size() == w_params.n());
292 std::vector<seal::Plaintext> encoded = m_p_workload->encodeVector(clear_param);
295 InternalParam<seal::Plaintext> retval;
296 retval.samples = std::move(encoded);
298 retval.tag = InternalParamInfo::tagPlaintext;
300 return this->getEngine().createHandle<decltype(retval)>(
301 sizeof(seal::Plaintext) * retval.samples.size(),
315 const InternalParam<seal::Plaintext> &encoded_data =
316 this->getEngine().retrieveFromHandle<InternalParam<seal::Plaintext>>(h_encoded_data, InternalParamInfo::tagPlaintext);
320 std::vector<std::vector<std::int64_t>> clear_result = m_p_workload->decodeResult(encoded_data.samples);
326 std::uint64_t min_sample_count = std::min(native_datapack.
buffer_count, clear_result.size());
327 for (std::uint64_t sample_i = 0; sample_i < min_sample_count; ++sample_i)
332 const std::vector<std::int64_t> &decoded = clear_result[sample_i];
333 std::uint64_t min_size = std::min(decoded.size(), native_sample.
size /
sizeof(std::int64_t));
334 std::copy_n(decoded.begin(), min_size,
335 reinterpret_cast<std::int64_t *
>(native_sample.
p));
345 const InternalParam<seal::Plaintext> &encoded_parameter =
346 this->getEngine().retrieveFromHandle<InternalParam<seal::Plaintext>>(h_encoded_parameters,
347 InternalParamInfo::tagPlaintext);
351 std::vector<seal::Ciphertext> encrypted = m_p_workload->encryptVector(encoded_parameter.samples);
355 InternalParam<seal::Ciphertext> retval;
356 retval.samples = std::move(encrypted);
357 retval.param_position = encoded_parameter.param_position;
358 retval.tag = InternalParamInfo::tagCiphertext;
360 return this->getEngine().createHandle<decltype(retval)>(
361 sizeof(seal::Ciphertext) * retval.samples.size(),
372 const InternalParam<seal::Ciphertext> &encrypted_data =
373 this->getEngine().retrieveFromHandle<InternalParam<seal::Ciphertext>>(h_encrypted_data, InternalParamInfo::tagCiphertext);
376 assert(encrypted_data.param_position == 0);
379 std::vector<seal::Plaintext> encoded_data_samples = m_p_workload->decryptResult(encrypted_data.samples);
383 InternalParam<seal::Plaintext> retval;
384 retval.samples = std::move(encoded_data_samples);
385 retval.param_position = encrypted_data.param_position;
386 retval.tag = InternalParamInfo::tagPlaintext;
388 return this->getEngine().createHandle<decltype(retval)>(
389 sizeof(seal::Plaintext) * retval.samples.size(),
399 assert(count == TutorialEltwiseAddBenchmarkDescription::ParametersCount);
402 std::pair<std::vector<seal::Plaintext>, std::vector<seal::Ciphertext>> params;
407 for (std::size_t handle_i = 0; handle_i < count; ++handle_i)
410 const InternalParamInfo ¶m_info =
411 this->getEngine().retrieveFromHandle<InternalParamInfo>(p_local_data[handle_i]);
412 assert(param_info.param_position < TutorialEltwiseAddBenchmarkDescription::ParametersCount);
414 switch (param_info.param_position)
418 if (!params.first.empty())
422 const InternalParam<seal::Plaintext> &internal_param =
423 this->getEngine().retrieveFromHandle<InternalParam<seal::Plaintext>>(p_local_data[handle_i],
424 InternalParamInfo::tagPlaintext);
426 params.first = internal_param.samples;
431 if (!params.second.empty())
435 const InternalParam<seal::Ciphertext> &internal_param =
436 this->getEngine().retrieveFromHandle<InternalParam<seal::Ciphertext>>(p_local_data[handle_i],
437 InternalParamInfo::tagCiphertext);
439 params.second = internal_param.samples;
447 return this->getEngine().createHandle<decltype(params)>(
449 InternalParamInfo::tagPlaintext | InternalParamInfo::tagCiphertext,
466 p_local_data[0] = this->getEngine().duplicateHandle(h_remote_data,
467 InternalParamInfo::tagCiphertext);
478 const std::pair<std::vector<seal::Plaintext>, std::vector<seal::Ciphertext>> ¶ms =
479 this->getEngine().retrieveFromHandle<std::pair<std::vector<seal::Plaintext>, std::vector<seal::Ciphertext>>>(
480 h_remote_packed, InternalParamInfo::tagCiphertext | InternalParamInfo::tagPlaintext);
483 const std::vector<seal::Plaintext> &A = params.first;
484 const std::vector<seal::Ciphertext> &B = params.second;
488 std::array<std::size_t, TutorialEltwiseAddBenchmarkDescription::ParametersCount> param_size;
489 param_size[0] = A.size();
490 param_size[1] = B.size();
491 std::uint64_t results_count = 1;
492 for (std::size_t param_i = 0; param_i < TutorialEltwiseAddBenchmarkDescription::ParametersCount; ++param_i)
494 if (p_param_indexers[param_i].value_index >= param_size[param_i])
496 std::stringstream ss;
497 ss <<
"Invalid parameter indexer for operation parameter " << param_i <<
". Expected index in range [0, "
498 << param_size[param_i] <<
"), but " << p_param_indexers[param_i].
value_index <<
" received.";
502 else if (p_param_indexers[param_i].value_index + p_param_indexers[param_i].batch_size > param_size[param_i])
504 std::stringstream ss;
505 ss <<
"Invalid parameter indexer for operation parameter " << param_i <<
". Expected batch size in range [1, "
506 << param_size[param_i] - p_param_indexers[param_i].
value_index <<
"], but " << p_param_indexers[param_i].
batch_size <<
" received.";
510 results_count *= p_param_indexers[param_i].
batch_size;
515 std::vector<seal::Ciphertext> result = m_p_workload->eltwiseadd(A, B);
516 assert(result.size() == results_count);
521 InternalParam<seal::Ciphertext> retval;
522 retval.samples = std::move(result);
523 retval.param_position = 0;
524 retval.tag = InternalParamInfo::tagCiphertext;
528 return this->getEngine().createHandle<decltype(retval)>(
529 sizeof(seal::Ciphertext) * retval.samples.size(),
Top level opaque benchmark class.
Base class that encapsulates common behavior of backend engines.
std::uint64_t n() const
Number elements in a vector.
#define HEBERROR_MSG_CLASS(message)
@ Int64
64 bits signed integers.
ErrorCode encrypt(Handle h_benchmark, Handle h_plaintext, Handle *h_ciphertext)
Encrypts a plain text into a cipher text.
ErrorCode operate(Handle h_benchmark, Handle h_remote_packed_params, const ParameterIndexer *p_param_indexers, uint64_t indexers_count, Handle *h_remote_output)
Performs the workload operation of the benchmark.
std::uint64_t count
Number of workload parameters.
DataPack * p_data_packs
Collection of data packs.
ErrorCode encode(Handle h_benchmark, const DataPackCollection *p_parameters, Handle *h_plaintext)
Given a pack of parameters in raw, native data format, encodes them into plain text suitable for back...
std::uint64_t value_index
Index of parameter value inside the data pack.
ErrorCode decrypt(Handle h_benchmark, Handle h_ciphertext, Handle *h_plaintext)
Decrypts a cipher text into corresponding plain text.
ErrorCode store(Handle h_benchmark, Handle h_remote, Handle *h_local_packed_params, std::uint64_t local_count)
Retrieves the specified data from the backend.
std::uint64_t pack_count
Number of data packs in the collection.
ErrorCode createBenchmark(Handle h_engine, Handle h_bench_desc, const WorkloadParams *p_params, Handle *h_benchmark)
Instantiates a benchmark on the backend.
std::uint64_t batch_size
Number of values to use, starting from index.
std::uint64_t size
Size of underlying data.
std::uint64_t param_position
The 0-based position of this parameter in the corresponding function call.
void * p
Pointer to underlying data.
ErrorCode load(Handle h_benchmark, const Handle *h_local_packed_params, std::uint64_t local_count, Handle *h_remote)
Loads the specified data from the local host into the remote backend to use as parameter during a cal...
std::uint64_t buffer_count
Number of data buffers in p_buffers.
ErrorCode decode(Handle h_benchmark, Handle h_plaintext, DataPackCollection *p_native)
Decodes plaintext data into the appropriate raw, native format.
NativeDataBuffer * p_buffers
Array of data buffers for parameter.
Workload
Defines all possible workloads.
Defines a benchmark test.
Defines a data package for an operation.
Defines a collection of data packs.
Specifies the parameters for a workload.
Structure to contain flexible data.
std::string to_string(const std::string_view &s)
#define HEBENCH_ECODE_INVALID_ARGS
Indicates invalid arguments to function call.
#define HEBENCH_ECODE_CRITICAL_ERROR
Specifies a critical error.
#define HEBENCH_HE_SCHEME_BFV