参考文献:
- 编译 OpenFHE
- OpenFHE 源码解析:PKE 部分
- [ABB+22] Al Badawi A, Bates J, Bergamaschi F, et al. Openfhe: Open-source fully homomorphic encryption library[C]//Proceedings of the 10th Workshop on Encrypted Computing & Applied Homomorphic Cryptography. 2022: 53-63.
文章目录
VSCode 的配置
编辑器
c_cpp_properties.json
如下:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/include/openfhe/pke",
"/usr/local/include/openfhe/core",
"/usr/local/include/openfhe",
"/usr/local/include/openfhe/binfhe"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++14",
"intelliSenseMode": "macos-gcc-x64"
}
],
"version": 4
}
调试器
tasks.json
如下:
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc 生成活动文件",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"-I/usr/local/include/openfhe",
"-I/usr/local/include/openfhe/pke",
"-I/usr/local/include/openfhe/core",
"-I/usr/local/include/openfhe/binfhe",
"-I/usr/local/include/openfhe/cereal",
"-L/usr/local/lib",
"-lOPENFHEcore",
"-lOPENFHEpke",
"-lOPENFHEbinfhe",
"-lssl",
"-lntl",
"-lgmp",
"-lgf2x",
"-lstdc++",
"-lm",
"-fopenmp",
"-fPIC",
"-Wl,--copy-dt-needed-entries"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
GCC 的配置
CMakeLists.txt
如下:
cmake_minimum_required(VERSION 3.10)
project(MyCode CXX)
set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#配置编译选项
add_compile_options(
-march=native -O3
-lstdc++ -lm -lssl -lgmp -lntl -pthread -fopenmp -fPIC
-mavx2 -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store
-Wno-unused-command-line-argument -Wwrite-strings -v
)
#配置头文件和静态库的路径
add_compile_options(
-I/usr/local/include/openfhe
-I/usr/local/include/openfhe/core
-I/usr/local/include/openfhe/pke
-I/usr/local/include/openfhe/binfhe
-I/usr/local/include/openfhe/cereal
-L/usr/local/lib
)
#SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--copy-dt-needed-entries") #递归获取动态库的依赖项
add_executable(use_ckks use_ckks.cpp)
target_link_libraries(use_ckks OPENFHEcore OPENFHEpke OPENFHEbinfhe)
add_executable(use_bgv use_bgv.cpp)
target_link_libraries(use_bgv OPENFHEcore OPENFHEpke OPENFHEbinfhe)
add_executable(use_bfv use_bfv.cpp)
target_link_libraries(use_bfv OPENFHEcore OPENFHEpke OPENFHEbinfhe)
BFV
代码
BFV 方案使用 MSD 纠错码,不需要模切换。在 Ciphertext<DCRTPoly>
密文中,GetLevel()
总是等于
0
0
0,GetNoiseScaleDeg()
记录了乘法深度,GetElements().size()
是密文中环元素向量的长度。
对于 CoefPackedPlaintext
打包,明文模数可以是任意的整数,不仅仅是素数或者素数幂。
系数打包的 BFV 用例,
#include <vector>
#include <iostream>
#include "openfhe.h"
#include "cputimer.h"
using namespace std;
using namespace lbcrypto;
#define endl2 endl << endl
#define pn puts("")
#define print_param(ct) \
cout << "Level = " << ct->GetLevel() << " | " \
<< "Depth = " << ct->GetNoiseScaleDeg() << " | " \
<< "SKDeg = " << ct->GetElements().size() - 1 << " | " \
<< endl;
#define print_pt(pt) \
cout << "Result: " << pt << endl2;
int main()
{
GetFrequency();
cout << endl;
size_t ringDim = 16384; // 必须是二的幂次
size_t plaintextModulus = 17; // 系数打包可以是任意整数
size_t multDepth = 10;
size_t maxRelinSkDeg = 4;
CCParams<CryptoContextBFVRNS> parameters;
parameters.SetSecurityLevel(HEStd_NotSet); // 如果不设置安全级别,则需要手动给出环维度
parameters.SetRingDim(ringDim);
parameters.SetPlaintextModulus(plaintextModulus);
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetMaxRelinSkDeg(maxRelinSkDeg);
parameters.SetKeySwitchTechnique(HYBRID);
// BEHZ,整数指令的 RNS 扩展,乘法速度很慢
// HPSPOVERQLEVELED,浮点指令的 RNS 扩展,并且隐式模切换
parameters.SetMultiplicationTechnique(HPSPOVERQLEVELED);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
cout << "CyclotomicOrder = " << cc->GetCyclotomicOrder() << endl
<< "RingDimension = " << cc->GetRingDimension() << endl
<< "Level = " << cc->GetKeyGenLevel() << endl
<< "Modulus = " << cc->GetModulus() << endl
<< "ModulusBits = " << cc->GetModulus().GetLengthForBase(2) << endl
<< "RootOfUnity = " << cc->GetRootOfUnity() << endl
<< "PlaintextModulus = " << cc->GetEncodingParams()->GetPlaintextModulus() << endl
<< "BatchSize = " << cc->GetEncodingParams()->GetBatchSize() << endl
<< "PlaintextGenerator = " << cc->GetEncodingParams()->GetPlaintextGenerator() << endl
<< endl2;
/***************************************************************************************************/
auto keys = cc->KeyGen();
cc->EvalMultKeysGen(keys.secretKey);
cc->EvalRotateKeyGen(keys.secretKey, {1, -2});
// 生成元 g = 5 mod N, ord(g) = N/2
map<usint, EvalKey<DCRTPoly>> evk_map = *cc->EvalAutomorphismKeyGen(keys.secretKey, {1u, 5u, 25u});
vector<int64_t> x1 = {1, 2, 3, 4, 5, 6, 7, 8};
vector<int64_t> x2 = {1, 0, 0, 0, 0, 0, 0, -1};
Plaintext pt1 = cc->MakeCoefPackedPlaintext(x1);
Plaintext pt2 = cc->MakeCoefPackedPlaintext(x2);
print_pt(pt1);
print_pt(pt2);
/***************************************************************************************************/
auto ct1 = cc->Encrypt(keys.publicKey, pt1);
auto ct2 = cc->Encrypt(keys.publicKey, pt2);
Plaintext pt;
print_param(ct1);
pn;
cc->Decrypt(keys.secretKey, ct1, &pt);
print_pt(pt);
cc->Decrypt(keys.secretKey, ct2, &pt);
print_pt(pt);
Ciphertext<DCRTPoly> ct;
cout.precision(8);
/***************************************************************************************************/
Timer("+", ct = ct1 + ct2;); // 比 cc->EvalAdd 要快
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #1", ct = cc->EvalAdd(ct1, ct2);); // 首先会 type 检查
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Scale", ct = cc->EvalMult(ct, cc->MakeCoefPackedPlaintext({0, 2}));); // 必须把 scale 先构造为 Plaintext
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #2", ct = cc->EvalAdd(ct, ct2);); // 相同 Level 不同 ScalingFactorInt 的加法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("*", ct = ct1 * ct2;); // 和 cc->EvalMult 一样,但是不检查 type
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult", ct = cc->EvalMult(ct1, ct2);); // 总是自动密钥切换,和 cc->EvalMultAndRelinearize 完全一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #3", ct = cc->EvalAdd(ct, ct2);); // 不同 Level 不同 ScalingFactorInt 的加法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult And Relinearize", ct = cc->EvalMultAndRelinearize(ct1, ct2);); // 和 cc->EvalMult 基本一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Mult No Relin #1", ct = cc->EvalMultNoRelin(ct1, ct2);); // 这个才是不做密钥切换的,SKDeg 增长
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult No Relin #2", ct = cc->EvalMultNoRelin(ct, ct2);); // 不同 ScalingFactor 不同 Level 的乘法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Relinear", cc->RelinearizeInPlace(ct);); // 占据几乎全部的时间
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Rotate(1)", ct = cc->EvalRotate(ct1, 1);); // 正数是左旋
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Rotate(-2)", ct = cc->EvalRotate(ct1, -2);); // 负数是右旋
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Automorphism(1)", ct = cc->EvalAutomorphism(ct1, 1, evk_map);); // 不旋转
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(5)", ct = cc->EvalAutomorphism(ct1, 5, evk_map);); // 数量 N 的明文槽,由 (-5) 生成
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(25)", ct = cc->EvalAutomorphism(ct1, 25, evk_map);); // 5^2 mod N
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
return 0;
}
结果
使用 BEHZ
乘法
CPU Frequency = 2918913687
CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 1532495540865662914854395520533418584588770550682052609
ModulusBits = 180
RootOfUnity = 0
PlaintextModulus = 17
BatchSize = 1024
PlaintextGenerator = 0
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 1 0 0 0 0 0 0 -1 ... )
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 1 0 0 0 0 0 0 -1 ... )
Running Time of <+>: 99032 cycles ( 0.033928 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 2 3 4 5 6 7 7 ... )
Running Time of <Add #1>: 2736272 cycles ( 0.937428 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 2 3 4 5 6 7 7 ... )
Running Time of <Scale>: 2735077 cycles ( 0.937019 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 0 4 4 6 8 -7 -5 -3 -3 ... )
Running Time of <Add #2>: 1133253 cycles ( 0.388245 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 4 4 6 8 -7 -5 -4 -3 ... )
Running Time of <*>: 253469802 cycles ( 86.837032 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult>: 187670910 cycles ( 64.294779 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Add #3>: 435927 cycles ( 0.149346 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 2 2 3 4 5 6 7 6 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult And Relinearize>: 126839959 cycles ( 43.454508 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult No Relin #1>: 130843571 cycles ( 44.826119 ms)
Level = 0 | Depth = 2 | SKDeg = 2 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult No Relin #2>: 172007707 cycles ( 58.928672 ms)
Level = 0 | Depth = 3 | SKDeg = 3 |
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )
Running Time of <Relinear>: 208823169 cycles ( 71.541399 ms)
Level = 0 | Depth = 3 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )
Running Time of <Rotate(1)>: 115388270 cycles ( 39.531237 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )
Running Time of <Rotate(-2)>: 70254530 cycles ( 24.068725 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 ... )
Running Time of <Automorphism(1)>: 83246053 cycles ( 28.519532 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Running Time of <Automorphism(5)>: 74563676 cycles ( 25.545009 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )
Running Time of <Automorphism(25)>: 67644689 cycles ( 23.174611 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 ... )
使用 HPSPOVERQLEVELED
乘法
CPU Frequency = 2918959071
CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 1532495540865662914854395520533418584588770550682052609
ModulusBits = 180
RootOfUnity = 0
PlaintextModulus = 17
BatchSize = 1024
PlaintextGenerator = 0
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 1 0 0 0 0 0 0 -1 ... )
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 1 0 0 0 0 0 0 -1 ... )
Running Time of <+>: 115828 cycles ( 0.039681 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 2 3 4 5 6 7 7 ... )
Running Time of <Add #1>: 4293174 cycles ( 1.470789 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 2 3 4 5 6 7 7 ... )
Running Time of <Scale>: 894332 cycles ( 0.306387 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 0 4 4 6 8 -7 -5 -3 -3 ... )
Running Time of <Add #2>: 987738 cycles ( 0.338387 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 4 4 6 8 -7 -5 -4 -3 ... )
Running Time of <*>: 236847696 cycles ( 81.141150 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult>: 162997593 cycles ( 55.841000 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Add #3>: 311286 cycles ( 0.106643 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 2 2 3 4 5 6 7 6 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult And Relinearize>: 152945198 cycles ( 52.397171 ms)
Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult No Relin #1>: 108039418 cycles ( 37.012995 ms)
Level = 0 | Depth = 2 | SKDeg = 2 |
Result: ( 1 2 3 4 5 6 7 7 -2 -3 -4 -5 -6 -7 -8 ... )
Running Time of <Mult No Relin #2>: 183090958 cycles ( 62.724743 ms)
Level = 0 | Depth = 3 | SKDeg = 3 |
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )
Running Time of <Relinear>: 116302449 cycles ( 39.843809 ms)
Level = 0 | Depth = 3 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 6 -4 -6 -8 7 5 3 2 2 3 4 5 6 7 8 ... )
Running Time of <Rotate(1)>: 88811197 cycles ( 30.425640 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )
Running Time of <Rotate(-2)>: 87308745 cycles ( 29.910918 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8 ... )
Running Time of <Automorphism(1)>: 87723653 cycles ( 30.053060 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Running Time of <Automorphism(5)>: 97097626 cycles ( 33.264470 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 0 0 8 ... )
Running Time of <Automorphism(25)>: 80256150 cycles ( 27.494784 ms)
Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 ... )
BGV
代码
BGV 方案使用 LSD 纠错码,需要模切换。在 Ciphertext<DCRTPoly>
密文中,GetScalingFactorInt()
记录了扭曲因子,GetLevel()
记录了乘法深度,GetNoiseScaleDeg()
记录了扭曲因子的指数,GetElements().size()
是密文中环元素向量的长度。
对于 PackedPlaintext
打包,明文模数必须是满足 NTT 的大素数,槽旋转对应的自同构指标由 5 mod{2*N}
生成。
槽打包的 BGV 用例,
#include <vector>
#include <iostream>
#include "openfhe.h"
#include "cputimer.h"
using namespace std;
using namespace lbcrypto;
#define endl2 endl << endl
#define pn puts("")
#define print_param(ct) \
cout << "ScalingFactorInt = " << ct->GetScalingFactorInt().ToString() << " | " \
<< "Level = " << ct->GetLevel() << " | " \
<< "Depth = " << ct->GetNoiseScaleDeg() << " | " \
<< "SKDeg = " << ct->GetElements().size() - 1 << " | " \
<< endl;
#define print_pt(pt) \
cout << "Result: " << pt << endl2;
int main()
{
GetFrequency();
cout << endl;
size_t ringDim = 16384; // 必须是二的幂次
size_t plaintextModulus = 65537; // 槽打包必须是大素数
size_t multDepth = 10;
size_t maxRelinSkDeg = 4;
CCParams<CryptoContextBGVRNS> parameters;
parameters.SetSecurityLevel(HEStd_NotSet); // 如果不设置安全级别,则需要手动给出环维度
parameters.SetRingDim(ringDim);
parameters.SetPlaintextModulus(plaintextModulus);
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetMaxRelinSkDeg(maxRelinSkDeg);
parameters.SetKeySwitchTechnique(HYBRID);
// FIXEDMANUAL 手动模切换,ScalingFactorInt 总是 1
// FLEXIBLEAUTO 自动模切换,ScalingFactorInt 会在 [0, plaintextModulus] 内变换
parameters.SetScalingTechnique(FLEXIBLEAUTO);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
cout << "CyclotomicOrder = " << cc->GetCyclotomicOrder() << endl
<< "RingDimension = " << cc->GetRingDimension() << endl
<< "Level = " << cc->GetKeyGenLevel() << endl
<< "Modulus = " << cc->GetModulus() << endl
<< "ModulusBits = " << cc->GetModulus().GetLengthForBase(2) << endl
<< "RootOfUnity = " << cc->GetRootOfUnity() << endl
<< "PlaintextModulus = " << cc->GetEncodingParams()->GetPlaintextModulus() << endl
<< "BatchSize = " << cc->GetEncodingParams()->GetBatchSize() << endl
<< "PlaintextGenerator = " << cc->GetEncodingParams()->GetPlaintextGenerator() << endl
<< endl2;
/***************************************************************************************************/
auto keys = cc->KeyGen();
cc->EvalMultKeysGen(keys.secretKey);
cc->EvalRotateKeyGen(keys.secretKey, {1, -2});
// 生成元 g = 5 mod N, ord(g) = N/2
map<usint, EvalKey<DCRTPoly>> evk_map = *cc->EvalAutomorphismKeyGen(keys.secretKey, {1u, 5u, 25u});
vector<int64_t> x1 = {1, 2, 3, 4, 5, 6, 7, 8};
vector<int64_t> x2 = {4, 3, 2, 1, 1, 2, 3, 4};
Plaintext pt1 = cc->MakePackedPlaintext(x1);
Plaintext pt2 = cc->MakePackedPlaintext(x2);
print_pt(pt1);
print_pt(pt2);
/***************************************************************************************************/
auto ct1 = cc->Encrypt(keys.publicKey, pt1);
auto ct2 = cc->Encrypt(keys.publicKey, pt2);
Plaintext pt;
print_param(ct1);
pn;
cc->Decrypt(keys.secretKey, ct1, &pt);
print_pt(pt);
cc->Decrypt(keys.secretKey, ct2, &pt);
print_pt(pt);
Ciphertext<DCRTPoly> ct;
cout.precision(8);
/***************************************************************************************************/
Timer("+", ct = ct1 + ct2;); // 比 cc->EvalAdd 要快
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #1", ct = cc->EvalAdd(ct1, ct2);); // 首先会 type 检查
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Scale", ct = cc->EvalMult(ct, cc->MakePackedPlaintext(
vector<int64_t>(cc->GetEncodingParams()->GetBatchSize(), 4)));); // 必须把 scale 先构造为 Plaintext
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #2", ct = cc->EvalAdd(ct, ct2);); // 相同 Level 不同 ScalingFactorInt 的加法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("*", ct = ct1 * ct2;); // 和 cc->EvalMult 一样,但是不检查 type
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult", ct = cc->EvalMult(ct1, ct2);); // 总是自动密钥切换,和 cc->EvalMultAndRelinearize 完全一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Composed Mult #1", ct = cc->ComposedEvalMult(ct1, ct2);); // 密钥切换 + 模切换
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Composed Mult #2", ct = cc->ComposedEvalMult(ct, ct2);); // FLEXIBLEAUTO 在乘法之前做模切换,EXT 第一次乘法之前也做模切换
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #3", ct = cc->EvalAdd(ct, ct2);); // 不同 Level 不同 ScalingFactorInt 的加法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult And Relinearize", ct = cc->EvalMultAndRelinearize(ct1, ct2);); // 和 cc->EvalMult 基本一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Mult No Relin #1", ct = cc->EvalMultNoRelin(ct1, ct2);); // 这个才是不做密钥切换的,SKDeg 增长
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
// cc->ModReduceInPlace(ct);
Timer("Mult No Relin #2", ct = cc->EvalMultNoRelin(ct, ct2);); // 不同 ScalingFactor 不同 Level 的乘法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Relinear", cc->RelinearizeInPlace(ct);); // 占据几乎全部的时间
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("ModReduce", cc->ModReduceInPlace(ct);); // 降低一层的缩放
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Rotate(1)", ct = cc->EvalRotate(ct1, 1);); // 正数是左旋
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Rotate(-2)", ct = cc->EvalRotate(ct1, -2);); // 负数是右旋
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Automorphism(1)", ct = cc->EvalAutomorphism(ct1, 1, evk_map);); // 不旋转
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(5)", ct = cc->EvalAutomorphism(ct1, 5, evk_map);); // 数量 N 的明文槽,由 (-5) 生成
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(25)", ct = cc->EvalAutomorphism(ct1, 25, evk_map);); // 5^2 mod N
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
return 0;
}
结果
使用 FIXEDMANUAL
模切换
CPU Frequency = 2919164586
CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 101915945247153194422621674945726031044678923861288323567523751344699549609876260625831851757818456743873649587405440263849024730822259572880063879169
ModulusBits = 495
RootOfUnity = 0
PlaintextModulus = 65537
BatchSize = 1024
PlaintextGenerator = 0
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 4 3 2 1 1 2 3 4 ... )
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 4 3 2 1 1 2 3 4 ... )
Running Time of <+>: 928928 cycles ( 0.318217 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 5 5 5 5 6 8 10 12 ... )
Running Time of <Add #1>: 918166 cycles ( 0.314530 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 5 5 5 5 6 8 10 12 ... )
Running Time of <Scale>: 1406846 cycles ( 0.481934 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 20 20 20 20 24 32 40 48 ... )
Running Time of <Add #2>: 721196 cycles ( 0.247056 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 24 23 22 21 25 34 43 52 ... )
Running Time of <*>: 98448862 cycles ( 33.725012 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Mult>: 74771761 cycles ( 25.614096 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Composed Mult #1>: 103001350 cycles ( 35.284530 ms)
ScalingFactorInt = 1 | Level = 1 | Depth = 1 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Composed Mult #2>: 97931103 cycles ( 33.547647 ms)
ScalingFactorInt = 1 | Level = 2 | Depth = 1 | SKDeg = 1 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <Add #3>: 660204 cycles ( 0.226162 ms)
ScalingFactorInt = 1 | Level = 2 | Depth = 1 | SKDeg = 1 |
Result: ( 20 21 14 5 6 26 66 132 ... )
Running Time of <Mult And Relinearize>: 121328656 cycles ( 41.562801 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Mult No Relin #1>: 1237702 cycles ( 0.423992 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 2 | SKDeg = 2 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Mult No Relin #2>: 1619596 cycles ( 0.554815 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 3 | SKDeg = 3 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <Relinear>: 207136845 cycles ( 70.957577 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 3 | SKDeg = 1 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <ModReduce>: 991996 cycles ( 0.339822 ms)
ScalingFactorInt = 1 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <Rotate(1)>: 82565072 cycles ( 28.283802 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )
Running Time of <Rotate(-2)>: 118772481 cycles ( 40.687148 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 0 0 1 2 3 4 5 6 7 8 ... )
Running Time of <Automorphism(1)>: 98264131 cycles ( 33.661730 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Running Time of <Automorphism(5)>: 104197049 cycles ( 35.694133 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )
Running Time of <Automorphism(25)>: 96996770 cycles ( 33.227578 ms)
ScalingFactorInt = 1 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 ... )
使用 FLEXIBLEAUTO
模切换
CPU Frequency = 2919001454
CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 11090766327926935557496534795450603891404351373393750077990741913791395272295156970046992897184754308334673051240449197703818432513
ModulusBits = 433
RootOfUnity = 0
PlaintextModulus = 65537
BatchSize = 1024
PlaintextGenerator = 0
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 4 3 2 1 1 2 3 4 ... )
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Result: ( 4 3 2 1 1 2 3 4 ... )
Running Time of <+>: 876028 cycles ( 0.300112 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 5 5 5 5 6 8 10 12 ... )
Running Time of <Add #1>: 882874 cycles ( 0.302458 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 5 5 5 5 6 8 10 12 ... )
Running Time of <Scale>: 1067962 cycles ( 0.365866 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 20 20 20 20 24 32 40 48 ... )
Running Time of <Add #2>: 903446 cycles ( 0.309505 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 24 23 22 21 25 34 43 52 ... )
Running Time of <*>: 79417215 cycles ( 27.206980 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Mult>: 96562770 cycles ( 33.080754 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Composed Mult #1>: 74693744 cycles ( 25.588800 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Composed Mult #2>: 98139791 cycles ( 33.621015 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <Add #3>: 923506 cycles ( 0.316377 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ( 20 21 14 5 6 26 66 132 ... )
Running Time of <Mult And Relinearize>: 94704513 cycles ( 32.444147 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Mult No Relin #1>: 1258456 cycles ( 0.431126 ms)
ScalingFactorInt = 48252 | Level = 0 | Depth = 2 | SKDeg = 2 |
Result: ( 4 6 6 4 5 12 21 32 ... )
Running Time of <Mult No Relin #2>: 2055410 cycles ( 0.704148 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 3 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <Relinear>: 179685843 cycles ( 61.557298 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <ModReduce>: 6682 cycles ( 0.002289 ms)
ScalingFactorInt = 48252 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ( 16 18 12 4 5 24 63 128 ... )
Running Time of <Rotate(1)>: 109469187 cycles ( 37.502272 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )
Running Time of <Rotate(-2)>: 74563389 cycles ( 25.544142 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 0 0 1 2 3 4 5 6 7 8 ... )
Running Time of <Automorphism(1)>: 84518442 cycles ( 28.954573 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 1 2 3 4 5 6 7 8 ... )
Running Time of <Automorphism(5)>: 104449053 cycles ( 35.782460 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ... )
Running Time of <Automorphism(25)>: 75254525 cycles ( 25.780914 ms)
ScalingFactorInt = 20731 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ( 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 ... )
CKKS
代码
CKKS 方案不使用纠错码,但是把浮点数缩放为整数,需要重缩放。在 Ciphertext<DCRTPoly>
密文中,GetScalingFactor()
记录了缩放因子,GetLevel()
记录了乘法深度,GetNoiseScaleDeg()
记录了缩放因子的指数,GetElements().size()
是密文中环元素向量的长度。
对于 CKKSPackedPlaintext
打包,仅支持 Real()
部分的加解密。SetScalingModSize()
用于设置缩放因子的比特数,SetBatchSize()
用于设置明文槽的个数。对于 BatchSize <= RingDim/2
,打包成维度 2*BatchSize
的子环,槽旋转对应的自同构指标由 5 mod{4*BatchSize}
生成。
槽打包的 CKKS 用例,
#include <vector>
#include <iostream>
#include "openfhe.h"
#include "cputimer.h"
using namespace std;
using namespace lbcrypto;
#define endl2 endl << endl
#define pn puts("")
#define print_param(ct) \
cout << "ScalingFactor = " << ct->GetScalingFactor() << " | " \
<< "Level = " << ct->GetLevel() << " | " \
<< "Depth = " << ct->GetNoiseScaleDeg() << " | " \
<< "SKDeg = " << ct->GetElements().size() - 1 << " | " \
<< endl;
#define print_pt(pt) \
cout << "Result: "; \
PrintComplex(pt); \
cout << "Estimated precision in bits: " << pt->GetLogPrecision() << endl2;
void PrintComplex(Plaintext pt)
{
vector<complex<double>> value = pt->GetCKKSPackedValue();
size_t len = pt->GetLength();
cout << "(";
while (--len > 0)
if (value[len] != complex<double>(0, 0))
break;
for (int i = 0; i <= len; i++)
{
cout << value[i] << ", ";
}
cout << " ... ); "
<< "Estimated precision: " << pt->GetLogPrecision() << " bits" << endl;
}
int main()
{
GetFrequency();
cout << endl;
size_t ringDim = 16384; // 必须是二的幂次
size_t batchSize = 8; // 必须是 N/2 的因子,二的幂次
size_t scaleModSize = 50; // 仅支持至多 60-bit 尾数
size_t multDepth = 10;
size_t maxRelinSkDeg = 4;
CCParams<CryptoContextCKKSRNS> parameters;
parameters.SetSecurityLevel(HEStd_NotSet); // 如果不设置安全级别,则需要手动给出环维度
parameters.SetRingDim(ringDim);
parameters.SetBatchSize(batchSize);
parameters.SetScalingModSize(scaleModSize);
parameters.SetMultiplicativeDepth(multDepth);
parameters.SetMaxRelinSkDeg(maxRelinSkDeg);
parameters.SetKeySwitchTechnique(HYBRID);
// FIXEDMANUAL 手动模切换,ScalingFactor 会变
// FLEXIBLEAUTO 自动模切换,ScalingFactor 总是 2^scaleModSize
parameters.SetScalingTechnique(FIXEDMANUAL);
CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
cc->Enable(PKE);
cc->Enable(KEYSWITCH);
cc->Enable(LEVELEDSHE);
cc->Enable(ADVANCEDSHE);
cout << "CyclotomicOrder = " << cc->GetCyclotomicOrder() << endl
<< "RingDimension = " << cc->GetRingDimension() << endl
<< "Level = " << cc->GetKeyGenLevel() << endl
<< "Modulus = " << cc->GetModulus() << endl
<< "ModulusBits = " << cc->GetModulus().GetLengthForBase(2) << endl
<< "RootOfUnity = " << cc->GetRootOfUnity() << endl
<< "PlaintextModulus = " << cc->GetEncodingParams()->GetPlaintextModulus() << endl
<< "BatchSize = " << cc->GetEncodingParams()->GetBatchSize() << endl
<< "PlaintextGenerator = " << cc->GetEncodingParams()->GetPlaintextGenerator() << endl
<< endl2;
/***************************************************************************************************/
auto keys = cc->KeyGen();
cc->EvalMultKeysGen(keys.secretKey);
cc->EvalRotateKeyGen(keys.secretKey, {1, -2});
// 生成元 g = 5 mod{4*batchSize}, ord(g) = batchSize
map<usint, EvalKey<DCRTPoly>> evk_map = *cc->EvalAutomorphismKeyGen(keys.secretKey, {1u, 5u, 25u, 29u, 17u, 21u, 9u, 13u});
vector<complex<double>> x1 = {{0.25, 0.5}, {0.5, 1}, {0.75, 1.5}, {1, 2}, {2, 4}, {3, 6}, {4, 8}, {5, 10}};
vector<double> x2 = {5, 4, 3, 2, 1, 0.75, 0.5, 0.25};
Plaintext pt1 = cc->MakeCKKSPackedPlaintext(x1);
Plaintext pt2 = cc->MakeCKKSPackedPlaintext(x2);
print_pt(pt1); // 明文编码了 Re 以及 Im
print_pt(pt2);
/***************************************************************************************************/
auto ct1 = cc->Encrypt(keys.publicKey, pt1);
auto ct2 = cc->Encrypt(keys.publicKey, pt2);
Plaintext pt;
print_param(ct1);
pn;
cc->Decrypt(keys.secretKey, ct1, &pt); // 但是仅加密 Re 部分,丢弃 Im 部分,复制在 Z_{4*batchSize}^* = <-1, 5> 中的 <5> 和 <-5> 两行
print_pt(pt);
cc->Decrypt(keys.secretKey, ct2, &pt);
print_pt(pt);
Ciphertext<DCRTPoly> ct;
cout.precision(8);
/***************************************************************************************************/
Timer("+", ct = ct1 + ct2;); // 比 cc->EvalAdd 要快
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Add #1", ct = cc->EvalAdd(ct1, ct2);); // 首先会 type 检查
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Scale", ct = cc->EvalMult(ct1, 4);); // 速度接近 operator+
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
cc->RescaleInPlace(ct); // 相同 Level 不同 ScalingFactor 的加法,错误
Timer("Add #2", ct = cc->EvalAdd(ct, ct2);); // 相同 ScalingFactor 不同 Level 的加法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("*", ct = ct1 * ct2;); // 和 cc->EvalMult 一样,但是不检查 type
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult", ct = cc->EvalMult(ct1, ct2);); // 总是自动密钥切换,和 cc->EvalMultAndRelinearize 完全一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Composed Mult #1", ct = cc->ComposedEvalMult(ct1, ct2);); // 密钥切换 + 模切换
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Composed Mult #2", ct = cc->ComposedEvalMult(ct, ct2);); // FLEXIBLEAUTO 在乘法之前做模切换,EXT 第一次乘法之前也做模切换
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Mult And Relinearize", ct = cc->EvalMultAndRelinearize(ct1, ct2);); // 和 cc->EvalMult 基本一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Mult No Relin #1", ct = cc->EvalMultNoRelin(ct1, ct2);); // 这个才是不做密钥切换的,SKDeg 增长
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
// cc->RescaleInPlace(ct);
Timer("Mult No Relin #2", ct = cc->EvalMultNoRelin(ct, ct2);); // 不同 ScalingFactor 不同 Level 的乘法,正确
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Relinear", cc->RelinearizeInPlace(ct);); // 占据几乎全部的时间
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("ModReduce", cc->ModReduceInPlace(ct);); // 降低一层的缩放,和 cc->RescaleInPlace 完全一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Rescale", cc->RescaleInPlace(ct);); // 降低一层的缩放,和 cc->ModReduceInPlace 完全一样
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Rotate(1)", ct = cc->EvalRotate(ct1, 1);); // 正数是左旋
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Rotate(-2)", ct = cc->EvalRotate(ct1, -2);); // 负数是右旋
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
Timer("Automorphism(1)", ct = cc->EvalAutomorphism(ct1, 1, evk_map);); // 不旋转
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(5)", ct = cc->EvalAutomorphism(ct1, 5, evk_map);); // 次数 4*batchSize 的子环上,数量 batchSize 的明文槽,由 (-5) 生成
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(25)", ct = cc->EvalAutomorphism(ct1, 25, evk_map);); // 5^2 mod 32
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(29)", ct = cc->EvalAutomorphism(ct1, 29, evk_map);); // 5^3 mod 32
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(17)", ct = cc->EvalAutomorphism(ct1, 17, evk_map););
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(21)", ct = cc->EvalAutomorphism(ct1, 21, evk_map););
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(9)", ct = cc->EvalAutomorphism(ct1, 9, evk_map););
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
Timer("Automorphism(13)", ct = cc->EvalAutomorphism(ct1, 13, evk_map););
print_param(ct);
cc->Decrypt(keys.secretKey, ct, &pt);
print_pt(pt);
/***************************************************************************************************/
return 0;
}
结果
使用 FIXEDMANUAL
模切换
CPU Frequency = 2919133983
CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 3773962425391299449455856105110342697983390191203387110210545988123360807414630715088298851847265236596671914551723351177669086733035396939530237480795634800286060664833
ModulusBits = 561
RootOfUnity = 0
PlaintextModulus = 50
BatchSize = 8
PlaintextGenerator = 0
Result: ((0.25,0.5), (0.5,1), (0.75,1.5), (1,2), (2,4), (3,6), (4,8), (5,10), ... ); Estimated precision: 50 bits
Estimated precision in bits: 50
Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0), ... ); Estimated precision: 50 bits
Estimated precision in bits: 50
ScalingFactor = 1.1259e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <+>: 232698 cycles ( 0.079715 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Add #1>: 293886 cycles ( 0.100676 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Scale>: 218742 cycles ( 0.074934 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1,0), (2,0), (3,0), (4,0), (8,0), (12,0), (16,0), (20,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Add #2>: 138844 cycles ( 0.047563 ms)
ScalingFactor = 1.1258999e+15 | Level = 1 | Depth = 1 | SKDeg = 1 |
Result: ((6,0), (6,0), (6,0), (6,0), (9,0), (12.75,0), (16.5,0), (20.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <*>: 88682107 cycles ( 30.379595 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Mult>: 83510222 cycles ( 28.607876 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Composed Mult #1>: 125045991 cycles ( 42.836674 ms)
ScalingFactor = 1.1258999e+15 | Level = 1 | Depth = 1 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Composed Mult #2>: 126722970 cycles ( 43.411152 ms)
ScalingFactor = 1.1258999e+15 | Level = 2 | Depth = 1 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Mult And Relinearize>: 100906735 cycles ( 34.567353 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Mult No Relin #1>: 477430 cycles ( 0.163552 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 2 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Mult No Relin #2>: 1077588 cycles ( 0.369146 ms)
ScalingFactor = 1.4272477e+45 | Level = 0 | Depth = 3 | SKDeg = 3 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Relinear>: 162462043 cycles ( 55.654192 ms)
ScalingFactor = 1.4272477e+45 | Level = 0 | Depth = 3 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <ModReduce>: 390542 cycles ( 0.133787 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Rescale>: 294642 cycles ( 0.100935 ms)
ScalingFactor = 1.1258999e+15 | Level = 2 | Depth = 1 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Rotate(1)>: 85623396 cycles ( 29.331780 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Rotate(-2)>: 85083932 cycles ( 29.146977 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(1)>: 84371770 cycles ( 28.903014 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(5)>: 32532042 cycles ( 11.144415 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(25)>: 102897566 cycles ( 35.249347 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(29)>: 154811323 cycles ( 53.033305 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(17)>: 79522168 cycles ( 27.241699 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Automorphism(21)>: 72500099 cycles ( 24.836167 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(9)>: 82870142 cycles ( 28.388605 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(13)>: 84619741 cycles ( 28.987961 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
使用 FLEXIBLEAUTO
模切换
CPU Frequency = 2918792554
CyclotomicOrder = 2048
RingDimension = 1024
Level = 0
Modulus = 3773962422988620268549387626283230612775297831378964384076336766063448441293238012679355400777370037636733749256861996141103106549700437881327817936926763295941309458433
ModulusBits = 560
RootOfUnity = 0
PlaintextModulus = 50
BatchSize = 8
PlaintextGenerator = 0
Result: ((0.25,0.5), (0.5,1), (0.75,1.5), (1,2), (2,4), (3,6), (4,8), (5,10), ... ); Estimated precision: 50 bits
Estimated precision in bits: 50
Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0), ... ); Estimated precision: 50 bits
Estimated precision in bits: 50
ScalingFactor = 1.1259e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Result: ((5,0), (4,0), (3,0), (2,0), (1,0), (0.75,0), (0.5,0), (0.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <+>: 217702 cycles ( 0.074586 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Add #1>: 195658 cycles ( 0.067034 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((5.25,0), (4.5,0), (3.75,0), (3,0), (3,0), (3.75,0), (4.5,0), (5.25,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Scale>: 336894 cycles ( 0.115422 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1,0), (2,0), (3,0), (4,0), (8,0), (12,0), (16,0), (20,0), ... ); Estimated precision: 39 bits
Estimated precision in bits: 39
Running Time of <Add #2>: 474080 cycles ( 0.162423 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((6,0), (6,0), (6,0), (6,0), (9,0), (12.75,0), (16.5,0), (20.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <*>: 118372907 cycles ( 40.555437 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Mult>: 102517626 cycles ( 35.123300 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Composed Mult #1>: 68991449 cycles ( 23.636983 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Composed Mult #2>: 83294391 cycles ( 28.537277 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Mult And Relinearize>: 83116483 cycles ( 28.476324 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 1 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Mult No Relin #1>: 661054 cycles ( 0.226482 ms)
ScalingFactor = 1.2676506e+30 | Level = 0 | Depth = 2 | SKDeg = 2 |
Result: ((1.25,0), (2,0), (2.25,0), (2,0), (2,0), (2.25,0), (2,0), (1.25,0), ... ); Estimated precision: 40 bits
Estimated precision in bits: 40
Running Time of <Mult No Relin #2>: 1388252 cycles ( 0.475625 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 3 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 38 bits
Estimated precision in bits: 38
Running Time of <Relinear>: 161033258 cycles ( 55.171190 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 38 bits
Estimated precision in bits: 38
Running Time of <ModReduce>: 7684 cycles ( 0.002633 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 38 bits
Estimated precision in bits: 38
Running Time of <Rescale>: 1646 cycles ( 0.000564 ms)
ScalingFactor = 1.2676506e+30 | Level = 1 | Depth = 2 | SKDeg = 1 |
Result: ((6.25,0), (8,0), (6.75,0), (4,0), (2,0), (1.6875,0), (1,0), (0.3125,0), ... ); Estimated precision: 38 bits
Estimated precision in bits: 38
Running Time of <Rotate(1)>: 26580736 cycles ( 9.106758 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Rotate(-2)>: 17406282 cycles ( 5.963521 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(1)>: 41046903 cycles ( 14.062974 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(5)>: 37049927 cycles ( 12.693580 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(25)>: 98023806 cycles ( 33.583684 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((0.75,0), (1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Automorphism(29)>: 92120842 cycles ( 31.561284 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((1,0), (2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Automorphism(17)>: 87246888 cycles ( 29.891432 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((2,0), (3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41
Running Time of <Automorphism(21)>: 136802988 cycles ( 46.869719 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((3,0), (4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(9)>: 103675496 cycles ( 35.519995 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((4,0), (5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), ... ); Estimated precision: 42 bits
Estimated precision in bits: 42
Running Time of <Automorphism(13)>: 65311725 cycles ( 22.376282 ms)
ScalingFactor = 1.1258999e+15 | Level = 0 | Depth = 1 | SKDeg = 1 |
Result: ((5,0), (0.25,0), (0.5,0), (0.75,0), (1,0), (2,0), (3,0), (4,0), ... ); Estimated precision: 41 bits
Estimated precision in bits: 41