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