Comparison of CKKS scheme between OpenFHE and TenSeal

Hi,

I’m trying to compare CKKS scheme between OpenFHE and TenSeal in Python. The experiment settings are:

  • 128 security level
  • Polynomial degree (N) = 8192
  • First Mod Size (Q0) = 60
  • Scaling Mod Size = 49
  • Multiplicative depth = 2
  • Two float arrays, each has 1000 elements. One constant

The following execution time are measured:

  • Enc: encode + encrypt
  • AddCC: add two ciphertext
  • MultCC: multiply two ciphertext
  • MultCConst: multiply one ciphertext and a constant
  • DecAddCC: decrypt AddCC
  • DecMultCC: decrypt MultCC
  • DecMultCConst: decrypt MultCConst

Each operation is executed 500 times and taken average with 12th Gen Intel® Core™ i7-12700KF CPU.

Based on the result, time taken for OpenFHE is longer than TenSeal, especially for decryption.

May I ask what may be the potential cause that makes OpenFHE takes more time compared to TenSeal?

Thank you

1 Like

It looks like the runtimes are close for everything except for decryption and MultCC. Several remarks and suggestions/questions:

  • Decryption in OpenFHE also does flooding to provide some protection for scenarios where decryption results are (accidentally) shared (see Section 5.1 of Securing Approximate Homomorphic Encryption Using Differential Privacy for more details). This flooding involves somewhat expensive generating discrete Gaussians using a relatively large standard deviation. SEAL does not do any flooding. This is why the decryption is SEAL is faster. In other words, OpenFHE provides more security for CKKS by design.
  • For MultCC, it is not clear whether relinearization (more expensive than multiplication itself) is called. OpenFHE provides different options for relinearization/ley switching, such as BV and hybrid key switching + digit size/number of large digits. If relinearization is used, then the same mode in OpenFHE should be used for fairness of comparison. It is also not clear whether rescaling is called.
  • Typically the main bottleneck operations in homomorphic computations are key switching, e.g., rotation, and rescaling. They should be the primary benchmarks.
  • Was the timing done in the single-threaded mode for both libraries?

Hi ypolyakov,

Thank you for the explanation for decoding.

  • Settings for MultCC, both libraries are set with relinearization keys, and key switching was set as BV for OpenFHE CKKS in order to set the same polynomial degree and mod sizes in both libraries.
    When performing multiplying two ciphertexts, no relinearization was called:
    – OpenFHE: EvalMult(ctxt1, ctxt2)
    – TenSeal: ctxt1 * ctxt2

  • The time was measured in a single-threaded model for both libraries.

In OpenFHE, EvalMult(ctxt1, ctxt2) calls relinearization (a.k.a. Key Switching) internally. To evaluate multiplication without relinearization, you can use EvalMultNoRelin(ctxt1, ctxt2).

As @Caesar pointed out, EvalMult calls both EvalMultNoRelin and KeySwitch. The first one is many times faster for CKKS than the second one. So it is incorrect to compare multiplication w/o relinearization with just multiplication. In other words, the current MultCC benchmarking results are not correct, at least relinearization in the case of OpenFHE EvalMult is definitely called.

Hi Caesar and ypolyakov,

After using EvalMultNoRelin(ctxt1, ctxt2) to measure multiplication time, the average time is 1122 micro seconds, which is much quicker than using EvalMult(ctxt1, ctxt2).

In addition, it looks TenSeal also performs relinearization after multiplication:
source: Auto Relin, Rescale and ModSwitch

If both multiplication function use relinearization, is there other protection mechanism in EvalMult?

Thank you

What do you mean by protection algorithm?

Hi ypolyakov,

I’m wondering if there are some protection mechanisms in EvalMult(ctxt1, ctxt2), similar to flooding for decryption in OpenFHE.

Thank you

No, no flooding is needed during computations.

Thank you for the explanation, this makes me understand more about the execution time of operations in both libraries.

I have another question regarding to the filesize of ciphertexts based on the following settings:

  • 128 security level
  • Polynomial degree (N) = 8192
  • First Mod Size (Q0) = 60
  • Scaling Mod Size = 49
  • Multiplicative depth = 2
  • Two float arrays, each has 1000 elements.
  • For OpenFHE, the ciphertext of a float array is exported by function SerializeToFile()
  • For TenSeal, the ciphertext of a float array is exported by function serialize()

After exporting these files, the size are:

  • OpenFHE: 525.4 KB
  • TenSeal: 355.7 KB

I’m curious about why the ciphertext from OpenFHE is more than that from TenSeal.
Thank you

It is hard to say whether you are doing an-apple-to-apple comparison. For example, are all moduli the same? Is \log Q the same for both cases? Are you using the binary serialization for OpenFHE (not JSON)? OpenFHE ciphertexts include some metadata (which should be relatively small) and then use binary encoding to encode vectors of random-like integers. In other words, the size should be close to the optimal size (for efficiently packing vectors of random-like numbers). I am also not familiar with the internal implementation of serialization in SEAL. So I cannot really comment for this part.

Hi,
I set logQ the same for both libraries. For OpenFHE I use binary serialization.

Thank you for the explanations to my questions for comparing the two libraries, which make me understand details of CKKS in two implementation more!