microsoft / SEAL

Microsoft SEAL is an easy-to-use and powerful homomorphic encryption library.
https://www.microsoft.com/en-us/research/group/cryptography-research/
MIT License
3.62k stars 711 forks source link

Guide for achive x^4 for a naive profiling #633

Open mmazz opened 1 year ago

mmazz commented 1 year ago

I'm new in this world and one task that my advisor give was to implement a simple x^4.

The idea is to try an intensive workload for a domestic PC to do a naive profile using something like Perf.

I implement x^3 with no problem, but when I try x^4 I get wrong answers, even if use big parameters.

Here is what i have (working for x^3). I try different polynomial modulus, different coefficient modulus, etc. I know that doesn't exist THE way to choose the parameters, but some guide for the modulus array? Some guidance?

#include <iostream>
#include <vector>
#include <seal/seal.h>

using std::cout;
using std::endl;
using std::vector;
using namespace seal;

int main() {
    EncryptionParameters params(scheme_type::ckks);

    size_t poly_modulus_degree =  16384; // Try 32768 
    int depth = 2; // with 3 is for x^4
    params.set_poly_modulus_degree(poly_modulus_degree);
    params.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 60, 40, 40, 40, 40, 60 })); // For 32768 I try with { 60, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 60 }
    double scale = pow(2.0, 60);

    SEALContext context(params);
    KeyGenerator keygen(context);
    auto secret_key = keygen.secret_key();

    PublicKey public_key;
    keygen.create_public_key(public_key);
    RelinKeys relin_keys;
    keygen.create_relin_keys(relin_keys);

    Encryptor encryptor(context, public_key);
    Evaluator evaluator(context);
    Decryptor decryptor(context, secret_key);
    CKKSEncoder encoder(context);
    size_t slot_count = encoder.slot_count();

    cout << "Number of slots: " << slot_count << endl;

    vector<double> input;
    input.reserve(slot_count);
    double curr_point = 0;
    double step_size = 1.0 / (static_cast<double>(slot_count) - 1);
    for (size_t i = 0; i < slot_count; i++)
    {
        input.push_back(curr_point*0.5+1);
        curr_point += step_size;
    }
    vector<double> vect_mul;
    for (int i=0; i<input.size(); i++)
            vect_mul.push_back(input[i]);

    Plaintext x_plain;
    encoder.encode(input, scale, x_plain);

    Ciphertext x_encrypted;
    encryptor.encrypt(x_plain, x_encrypted);

    Ciphertext x1 = x_encrypted;
    Ciphertext x2 = x_encrypted;
    evaluator.square(x1, x2);
    evaluator.relinearize_inplace(x2, relin_keys);
    evaluator.rescale_to_next_inplace(x2);
    evaluator.rescale_to_next_inplace(x_encrypted);

    Ciphertext x3 = x2;
    evaluator.multiply_inplace(x3,x_encrypted);
    evaluator.relinearize_inplace(x3, relin_keys);
    evaluator.rescale_to_next_inplace(x_encrypted);
    evaluator.rescale_to_next_inplace(x3);

    Ciphertext x4 = x3;
    evaluator.multiply_inplace(x4,x_encrypted);
    evaluator.relinearize_inplace(x4, relin_keys);
    evaluator.rescale_to_next_inplace(x_encrypted);
    evaluator.rescale_to_next_inplace(x4);

    Plaintext plain_result;
    decryptor.decrypt(x4, plain_result);

    vector<double> result;
    encoder.decode(plain_result, result);

    for (int i=0; i<depth; i++){
        for (int i = 0; i < vect_mul.size(); i++) {
                vect_mul[i] *= input[i];
        }
    }

    for (int i=0; i<slot_count; i=i+100){
        cout << vect_mul[i] << " - "<< result[i] <<"\n";
    }

    return 0;
}
fionser commented 1 year ago