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

BGV: Add Variance-based Noise Model #1385

Merged
merged 1 commit into from
Feb 12, 2025

Conversation

ZenithalHourlyRate
Copy link
Collaborator

Depends on #1343. This adds a noise model based on variance analysis in coefficient embedding from MP24 (https://ia.cr/2019/452).

This model gives a much closer bound (tight in the means of off by 2~3 bit) on the noise, compared with the model in #1343 (off by > 10 bit). User can use such model to generate aggresive parameters.

One caution from my experiment is that, after a deep multiplication, this model gives underestimation. Fixes could be imported in a similar style from BMCM23 (https://ia.cr/2023/600), which focuses on BFV. This is a future work.

Example

For the most tailored example for Lattigo (merging #1379, #1374, #1380), we get the following trace and generated parameter

Public key enc

Change the public key encryption to mod reduce, suggested by #1374 (comment)

   // P stands for public key encryption
   if constexpr (P) {
-    return evalEncryptPk(param);
+    // return evalEncryptPk(param);
+    return evalModReduce(param, evalConstant(param));

Estimation and generated param

ringDim: 8192
plaintextModulus: 65537
level: 2
logqi: 25 22 30 
qi: 33832961 4423681 1073872897 
dnum: 2
logpi: 30 30 
pi: 1073971201 1074266113 
Noise Bound: 23.32 Budget: 52 Total: 77 for value: <block argument> of type 'tensor<8xi16>' at index: 0 
Noise Bound: 23.32 Budget: 52 Total: 77 for value: <block argument> of type 'tensor<8xi16>' at index: 1 
Noise Bound: 51.23 Budget: 24 Total: 77 for value: %1 = arith.muli %input0, %input1 {mgmt.mgmt = #mgmt.mgmt<level = 2, dimension = 3>} : tensor<8xi16> 
Noise Bound: 51.23 Budget: 24 Total: 77 for value: %2 = mgmt.relinearize %1 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 51.23 Budget: 24 Total: 77 for value: %3 = tensor_ext.rotate %2, %c4 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16>, index 
Noise Bound: 51.73 Budget: 24 Total: 77 for value: %4 = arith.addi %2, %3 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 51.73 Budget: 24 Total: 77 for value: %5 = tensor_ext.rotate %4, %c2 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16>, index 
Noise Bound: 52.23 Budget: 23 Total: 77 for value: %6 = arith.addi %4, %5 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 52.23 Budget: 23 Total: 77 for value: %7 = tensor_ext.rotate %6, %c1 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16>, index 
Noise Bound: 52.73 Budget: 23 Total: 77 for value: %8 = arith.addi %6, %7 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 23.32 Budget: 22 Total: 47 for value: %9 = mgmt.modreduce %8 {mgmt.mgmt = #mgmt.mgmt<level = 1>} : tensor<8xi16> 
Noise Bound: 44.53 Budget: 1 Total: 47 for value: %extracted = tensor.extract %9[%c7] {mgmt.mgmt = #mgmt.mgmt<level = 1>} : tensor<8xi16> 
Noise Bound: 23.32 Budget: 0 Total: 25 for value: %10 = mgmt.modreduce %extracted {mgmt.mgmt = #mgmt.mgmt<level = 0>} : i16 

Real trace

[1 2 3 4 5 6 7 8]
Noise: 22.43 Total: 77
[2 3 4 5 6 7 8 9]
Noise: 22.30 Total: 77
[2 6 12 20 30 42 56 72]
Noise: 49.88 Total: 77
[2 6 12 20 30 42 56 72]
Noise: 49.88 Total: 77
[30 42 56 72 2 6 12 20]
Noise: 49.88 Total: 77
[32 48 68 92 32 48 68 92]
Noise: 50.52 Total: 77
[68 92 32 48 68 92 32 48]
Noise: 50.52 Total: 77
[100 140 100 140 100 140 100 140]
Noise: 51.03 Total: 77
[140 100 140 100 140 100 140 100]
Noise: 51.03 Total: 77
[240 240 240 240 240 240 240 240]
Noise: 51.44 Total: 77
[240 240 240 240 240 240 240 240]
Noise: 22.52 Total: 47
[0 0 0 0 0 0 0 240]
Noise: 39.86 Total: 47
[240 0 0 0 0 0 0 0]
Noise: 39.86 Total: 47
[240 0 0 0 0 0 0 0]
Noise: 39.86 Total: 47
[240 0 0 0 0 0 0 0]
Noise: 22.63 Total: 25

Secret key enc

The estimation and generated param

ringDim: 8192
plaintextModulus: 65537
level: 2
logqi: 25 22 23 
qi: 33832961 4423681 8404993 
dnum: 2
logpi: 25 25 
pi: 34062337 34160641 
Noise Bound: 20.08 Budget: 48 Total: 70 for value: <block argument> of type 'tensor<8xi16>' at index: 0 
Noise Bound: 20.08 Budget: 48 Total: 70 for value: <block argument> of type 'tensor<8xi16>' at index: 1 
Noise Bound: 44.76 Budget: 24 Total: 70 for value: %1 = arith.muli %input0, %input1 {mgmt.mgmt = #mgmt.mgmt<level = 2, dimension = 3>} : tensor<8xi16> 
Noise Bound: 44.76 Budget: 24 Total: 70 for value: %2 = mgmt.relinearize %1 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 44.76 Budget: 24 Total: 70 for value: %3 = tensor_ext.rotate %2, %c4 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16>, index 
Noise Bound: 45.26 Budget: 23 Total: 70 for value: %4 = arith.addi %2, %3 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 45.26 Budget: 23 Total: 70 for value: %5 = tensor_ext.rotate %4, %c2 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16>, index 
Noise Bound: 45.76 Budget: 23 Total: 70 for value: %6 = arith.addi %4, %5 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 45.76 Budget: 23 Total: 70 for value: %7 = tensor_ext.rotate %6, %c1 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16>, index 
Noise Bound: 46.26 Budget: 22 Total: 70 for value: %8 = arith.addi %6, %7 {mgmt.mgmt = #mgmt.mgmt<level = 2>} : tensor<8xi16> 
Noise Bound: 23.32 Budget: 22 Total: 47 for value: %9 = mgmt.modreduce %8 {mgmt.mgmt = #mgmt.mgmt<level = 1>} : tensor<8xi16> 
Noise Bound: 44.53 Budget: 1 Total: 47 for value: %extracted = tensor.extract %9[%c7] {mgmt.mgmt = #mgmt.mgmt<level = 1>} : tensor<8xi16> 
Noise Bound: 23.32 Budget: 0 Total: 25 for value: %10 = mgmt.modreduce %extracted {mgmt.mgmt = #mgmt.mgmt<level = 0>} : i16

Real trace

[1 2 3 4 5 6 7 8]
Noise: 19.58 Total: 70
[2 3 4 5 6 7 8 9]
Noise: 19.58 Total: 70
[2 6 12 20 30 42 56 72]
Noise: 43.80 Total: 70
[2 6 12 20 30 42 56 72]
Noise: 43.80 Total: 70
[30 42 56 72 2 6 12 20]
Noise: 43.80 Total: 70
[32 48 68 92 32 48 68 92]
Noise: 44.25 Total: 70
[68 92 32 48 68 92 32 48]
Noise: 44.25 Total: 70
[100 140 100 140 100 140 100 140]
Noise: 44.74 Total: 70
[140 100 140 100 140 100 140 100]
Noise: 44.74 Total: 70
[240 240 240 240 240 240 240 240]
Noise: 45.14 Total: 70
[240 240 240 240 240 240 240 240]
Noise: 22.87 Total: 47
[0 0 0 0 0 0 0 240]
Noise: 40.22 Total: 47
[240 0 0 0 0 0 0 0]
Noise: 40.22 Total: 47
[240 0 0 0 0 0 0 0]
Noise: 40.22 Total: 47
[240 0 0 0 0 0 0 0]
Noise: 22.41 Total: 25

@j2kun
Copy link
Collaborator

j2kun commented Feb 11, 2025

This looks good, in line with the base PRs, and I suspect I won't have any serious changes once those are in and this is rebased.

@ZenithalHourlyRate ZenithalHourlyRate marked this pull request as ready for review February 12, 2025 00:35
@ZenithalHourlyRate
Copy link
Collaborator Author

Ready for review now.

@j2kun j2kun added the pull_ready Indicates whether a PR is ready to pull. The copybara worker will import for internal testing label Feb 12, 2025
@copybara-service copybara-service bot merged commit 7422199 into google:main Feb 12, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pull_ready Indicates whether a PR is ready to pull. The copybara worker will import for internal testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants