Measure the Operations in the Bootstrapping Pipeline

Hello, I would like to explore using CKKS/RNS bootstrapping and at the same time test various parameters and their impact on different algorithms in the bootstrapping pipeline such as ModUp, SubSum, CoeffToSlots, EvalSine, and SlotsToCoeff in terms of time and precision. Is there a way or procedure to extract this information? I would be very grateful for your help. Thank you.

Go to src/pke/lib/scheme/ckksrns/ckksrns-fhe.cpp, define BOOTSTRAPTIMING, and rebuild OpenFHE. When you invoke CKKS bootstrapping, you will be getting some timing printouts. Note that we do not recommend this except for research purposes.

Hey @Caesar, that works, that’s great! Could you tell me where exactly the evalsine is in there, or what the corresponding parameters are called? I would also like to perform the same measurement as shown in the screenshot. Thanks a lot.

The sine function evaluation is done by calling EvalChebyshevSeries. Note there are two cases of interest: sparse vs sully packed ciphertext bootstrapping.

Thank u a lot it works :slight_smile:

Hello @Caesar ,

I have extracted the respective parameters and evaluated them accordingly. Please see the screenshot. However, it seems that something is missing. The total runtime of the bootstrapping for one iteration is 167.6.

While the sum of the individual bootstrapping operations is 144.2. Therefore, my question is: Do you know what I may have forgotten or not found, and where this is in the code for ckksrns-fhe.cpp?

fyi: i use sparse

I am not sure what could have gone wrong in the timing. There is another step in CKKS bootstrapping RAISING THE MODULUS, I suggest you measure that step as well. Btw, are you bootstrapping an exhausted ciphertext - a ciphertext at the lowest level, that is, it cannot be computed upon anymore?

Hi @Caesar
Regarding the last part of your question, I didn’t quite understand it fully.

Specifically, what I am doing is testing various variations of the input parameters as seen in the screenshot.

I calculate the variance, mean value, and perform a rotation on encrypteted Data. Regarding your question, “Btw, are you bootstrapping an exhausted ciphertext - a ciphertext at the lowest level, that is, it cannot be computed upon anymore?” I didn’t fully understand this part. Have I configured something incorrectly, or is there a way to configure it differently? There are a few other values in the screenshot with explanations. If there are additional configuration options, I would appreciate more information to conduct a better analysis.

image

image

image

While it may not make a big difference, it is reasonable to emulate a realistic situation in your experiments. We usually bootstrap after exhausting the multiplicative depth of the ciphertext, that is, we cannot use the ciphertext anymore for further multiplications, at this stage, the ciphertext is termed exhausted.
To create an exhausted ciphertext, refer to the example at src/pke/examples/simple-ckks-bootstrapping.cpp, and check the lines:
Plaintext ptxt = cryptoContext->MakeCKKSPackedPlaintext(x, 1, depth - 1);
Ciphertext<DCRTPoly> ciph = cryptoContext->Encrypt(keyPair.publicKey, ptxt);

Here, ciph is exhausted and cannot be used for multiplication as it is encrypted at the lowest level possible.

For the timing issue, make sure you measure all operations in bootstrapping. The difference you experienced is huge and it is worth further investigation.

Without code, it is difficult to examine this. Feel free to share your full code on Github so we can take a look.