Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

correct bootstrap! and add use of batch size in init_bootstrapping #18

Merged
merged 13 commits into from
Feb 13, 2024

Conversation

ArseniyKholod
Copy link
Collaborator

@ArseniyKholod ArseniyKholod commented Jan 24, 2024

It solves issue #17.
As was discussed, I add possibility to use smaller length as ring_dim//2.
New functions:
init_bootstrapping!(context::SecureContext{<:OpenFHEBackend}, private_key::PrivateKey, length::Int)
For the same purpose I added:
PlainVector(data::Vector{Float64}, length::Int, context::SecureContext{<:OpenFHEBackend}) with user-chosen length of Plaintext.

I add also a duplicate for Unencrypted case, to be able to reuse the same code for unencrypted data.

Also OpenFHE.EvalBootstrap(cc, secure_vector.data) does not change the argument secure_vector.data itself, but returns new Ciphertext, that needs to be assigned as new secure_vector.data .

@sloede , I used length instead of num_slots. But I'm not really sure, if it's actually length. Because if I'm using for example 40 nodes, than I need num_slots=64 (nearest power of two). Actual length of data is Base.length(data) = 40 and capacity = OpenFHE.GetSlots(plaintext) is 64. May be it make sense to rename num_slots in functions of this PR to capacity, not length?

@sloede sloede self-requested a review January 24, 2024 10:33
Copy link

codecov bot commented Jan 24, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (3019450) 100.00% compared to head (346a39e) 100.00%.

❗ Current head 346a39e differs from pull request most recent head fcb1cb8. Consider uploading reports for the commit fcb1cb8 to get more accurate results

Additional details and impacted files
@@            Coverage Diff            @@
##              main       #18   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            8         8           
  Lines          309       310    +1     
=========================================
+ Hits           309       310    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@sloede
Copy link
Member

sloede commented Jan 24, 2024

I used length instead of num_slots. But I'm not really sure, if it's actually length. Because if I'm using for example 40 nodes, than I need num_slots=64 (nearest power of two). Actual length of data is Base.length(data) = 40 and capacity = OpenFHE.GetSlots(plaintext) is 64. May be it make sense to rename num_slots in functions of this PR to capacity, not length?

Is "your" length equal to what you specify as the "batch size" when you set up the CCParams? If yes, then it should be called "capacity" 👍 If not, then we might have a third number that is neither length nor capacity 🤔

To me, capacity is the physical limit of how much data can be stored in a given ciphertext/plaintext. it is a property of the FHE scheme. The length on the other hand is purely a convenience thing: when encoding a three-value vector, doing some FHE operations with it, and then decoding the result, I want to be retrieve a three-value vector again, not one that has 3 values of usable data and 5 values of garbage. Do you understand what I mean?

@sloede
Copy link
Member

sloede commented Jan 24, 2024

Also OpenFHE.EvalBootstrap(cc, secure_vector.data) does not change the argument secure_vector.data itself, but returns new Ciphertext, that needs to be assigned as new secure_vector.data .

OK, can you please fix this as well (if not yet done)?

@sloede
Copy link
Member

sloede commented Jan 24, 2024

length::Int --> please use length::Integer since Julia will do the appropriate conversion for us

@ArseniyKholod
Copy link
Collaborator Author

Also OpenFHE.EvalBootstrap(cc, secure_vector.data) does not change the argument secure_vector.data itself, but returns new Ciphertext, that needs to be assigned as new secure_vector.data .

OK, can you please fix this as well (if not yet done)?

It's already done in this PR

@ArseniyKholod
Copy link
Collaborator Author

ArseniyKholod commented Jan 24, 2024

I used length instead of num_slots. But I'm not really sure, if it's actually length. Because if I'm using for example 40 nodes, than I need num_slots=64 (nearest power of two). Actual length of data is Base.length(data) = 40 and capacity = OpenFHE.GetSlots(plaintext) is 64. May be it make sense to rename num_slots in functions of this PR to capacity, not length?

Is "your" length equal to what you specify as the "batch size" when you set up the CCParams? If yes, then it should be called "capacity" 👍 If not, then we might have a third number that is neither length nor capacity 🤔

To me, capacity is the physical limit of how much data can be stored in a given ciphertext/plaintext. it is a property of the FHE scheme. The length on the other hand is purely a convenience thing: when encoding a three-value vector, doing some FHE operations with it, and then decoding the result, I want to be retrieve a three-value vector again, not one that has 3 values of usable data and 5 values of garbage. Do you understand what I mean?

Ohh, naming is always difficult. If I undestand correctly batch_size is something you set during CryptoContext configuration for all Ciphertexts and Plaintexts you will create. But in this case it sets physical limit only for one particular Plaintext. It's probably smth third.

Yeah, as you said in your example, I would get now after decrypting not 3 values, but 8. And need to slice it by myself.

@sloede
Copy link
Member

sloede commented Jan 24, 2024

I used length instead of num_slots. But I'm not really sure, if it's actually length. Because if I'm using for example 40 nodes, than I need num_slots=64 (nearest power of two). Actual length of data is Base.length(data) = 40 and capacity = OpenFHE.GetSlots(plaintext) is 64. May be it make sense to rename num_slots in functions of this PR to capacity, not length?

Is "your" length equal to what you specify as the "batch size" when you set up the CCParams? If yes, then it should be called "capacity" 👍 If not, then we might have a third number that is neither length nor capacity 🤔
To me, capacity is the physical limit of how much data can be stored in a given ciphertext/plaintext. it is a property of the FHE scheme. The length on the other hand is purely a convenience thing: when encoding a three-value vector, doing some FHE operations with it, and then decoding the result, I want to be retrieve a three-value vector again, not one that has 3 values of usable data and 5 values of garbage. Do you understand what I mean?

Ohh, naming is always difficult. If I undestand correctly batch_size is something you set during CryptoContext configuration for all Ciphertexts and Plaintexts you will create. But in this case it sets physical limit only for one particular Plaintext. It's probably smth third.

Yeah, as you said in your example, I would get now after decrypting not 3 values, but 8. And need to slice it by myself.

IIUC from https://github.com/openfheorg/openfhe-development/blob/b2869aef5cf61afd364b3eaea748dcc8a7020b9c/src/pke/include/cryptocontext.h#L3244, what is expected here is the number of slots. Wouldn't this be the same as the batch size, i.e., what we call here capacity?

Maybe you can ask this on the OpenFHE Discourse forum, what the relation between ring dimension, batch size, num slots and length is, before we proceed here?

@ArseniyKholod
Copy link
Collaborator Author

I used length instead of num_slots. But I'm not really sure, if it's actually length. Because if I'm using for example 40 nodes, than I need num_slots=64 (nearest power of two). Actual length of data is Base.length(data) = 40 and capacity = OpenFHE.GetSlots(plaintext) is 64. May be it make sense to rename num_slots in functions of this PR to capacity, not length?

Is "your" length equal to what you specify as the "batch size" when you set up the CCParams? If yes, then it should be called "capacity" 👍 If not, then we might have a third number that is neither length nor capacity 🤔
To me, capacity is the physical limit of how much data can be stored in a given ciphertext/plaintext. it is a property of the FHE scheme. The length on the other hand is purely a convenience thing: when encoding a three-value vector, doing some FHE operations with it, and then decoding the result, I want to be retrieve a three-value vector again, not one that has 3 values of usable data and 5 values of garbage. Do you understand what I mean?

Ohh, naming is always difficult. If I undestand correctly batch_size is something you set during CryptoContext configuration for all Ciphertexts and Plaintexts you will create. But in this case it sets physical limit only for one particular Plaintext. It's probably smth third.
Yeah, as you said in your example, I would get now after decrypting not 3 values, but 8. And need to slice it by myself.

IIUC from https://github.com/openfheorg/openfhe-development/blob/b2869aef5cf61afd364b3eaea748dcc8a7020b9c/src/pke/include/cryptocontext.h#L3244, what is expected here is the number of slots. Wouldn't this be the same as the batch size, i.e., what we call here capacity?

Maybe you can ask this on the OpenFHE Discourse forum, what the relation between ring dimension, batch size, num slots and length is, before we proceed here?

From https://openfhe.discourse.group/t/relation-between-ring-dimension-batch-size-num-slots-and-length/1036

"When the number of slots is specified during MakeCKKSPackedPlaintext, that number of slots is set for a specific plaintext/ciphertext. The batch size is the global (default) setting for all ciphertexts in the cryptocontext."

It seems to be, that num_slots is capacity for specific entity, batch_size is default capacity in our case. So I should rename length -> capacity, when talking about num_slots. Am I rigth?

@sloede
Copy link
Member

sloede commented Jan 26, 2024

From https://openfhe.discourse.group/t/relation-between-ring-dimension-batch-size-num-slots-and-length/1036

"When the number of slots is specified during MakeCKKSPackedPlaintext, that number of slots is set for a specific plaintext/ciphertext. The batch size is the global (default) setting for all ciphertexts in the cryptocontext."

Thanks for asking there - this seems to be a very helpful answer for us!

It seems to be, that num_slots is capacity for specific entity, batch_size is default capacity in our case. So I should rename length -> capacity, when talking about num_slots. Am I rigth?

Yes, I think for SecureArithmetic.jl, we should make no difference between num_slots and batchSize - they both are equal and stored in capacity for. I do not see any reason for the moment to create SecureVectors of different slot_size, or do you?

Maybe, just to be sure, you can ask

  • Can num_slots be greater than the originally specified batchSize?
  • What is the motivation is to create Plaintexts with different num_slots from a single CryptoContext (CC)? Are there performance benefits?
  • Is it possible to do arithmetic with plaintext/ciphertests of different num_slots?
  • If the previous question was answered with "yes", and the one before that with "better performance", is there any reason to not always set num_slots to the smallest power-of-two such that the data fits?

Example for the last question: If batchSize == 128, but our data is either length == 30 or length == 50, should we just always set num_slots to 32 and 64 respectively?

@ArseniyKholod ArseniyKholod changed the title Add missing functionalities for first simulation correct bootstrap! and add use of batch size in init_bootstrapping Feb 13, 2024
@ArseniyKholod
Copy link
Collaborator Author

I removed all unnecessary changes in this PR, that could be solved by setting appropriate batch_size.

I changed bootstrap!, as OpenFHE.EvalBootstrap doesn't change cipher text that is passed to it.

And also I suggest to replace num_slots = div(ring_dimension, 2) by batch_size in init_bootrstapping! getting it through newly introduced EncodingParams. It allows to utilize user-chosen batch_size of cipher text to perform bootstrap!.

src/openfhe.jl Outdated Show resolved Hide resolved
src/openfhe.jl Outdated Show resolved Hide resolved
src/openfhe.jl Show resolved Hide resolved
ArseniyKholod and others added 3 commits February 13, 2024 18:59
Co-authored-by: Michael Schlottke-Lakemper <[email protected]>
Co-authored-by: Michael Schlottke-Lakemper <[email protected]>
Copy link
Member

@sloede sloede left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@sloede sloede merged commit 9c37201 into hpsc-lab:main Feb 13, 2024
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants