同态加密和SEAL库的介绍(十)CKKS 参数心得 2

打印 上一主题 下一主题

主题 510|帖子 510|积分 1530

写在前面:
        本篇继承上篇的测试,首先针对密文深度乘法情况,虽然密文乘法本就是应该尽量避免的(时间和内存本钱过高),更不用说深度乘法了,但是为了测试的完整性,还是做一下方便各人比对。
        其次是关于参数设置对内存占用的影响,这个非常紧张,由于我们在跑模型的时候,经常进程被 kill,由于确实是密文出乎料想的大,后面根据测试数据各人就能看出来。
一、测试设置

由于和之前的设置一样,这里就不多介绍了,直接放代码。
1.1 前置设置

  1. EncryptionParameters parms(scheme_type::ckks);
  2. size_t poly_modulus_degree = 8192;
  3. parms.set_poly_modulus_degree(poly_modulus_degree);
  4. parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 50, 30, 30, 50 }));
  5. double scale = pow(2.0, 30);
  6. SEALContext context(parms);
  7. KeyGenerator keygen(context);
  8. auto secret_key = keygen.secret_key();
  9. PublicKey public_key;
  10. keygen.create_public_key(public_key);
  11. RelinKeys relin_keys;
  12. keygen.create_relin_keys(relin_keys);
  13. GaloisKeys gal_keys;
  14. keygen.create_galois_keys(gal_keys);
  15. Encryptor encryptor(context, public_key);
  16. Evaluator evaluator(context);
  17. Decryptor decryptor(context, secret_key);
  18. CKKSEncoder encoder(context);
  19. size_t slot_count = encoder.slot_count();
复制代码
1.2 输入设置

为了具有对比参考代价,这里输入也设置成一样,不外对三个乘数举行加密。
  1. vector<double> the_input;
  2. the_input.reserve(slot_count);
  3. for (size_t i = 0; i < slot_count; i++){
  4.     the_input.push_back((double)i);
  5. }
  6. Plaintext the_input_plain;
  7. encoder.encode(the_input, scale, the_input_plain);
  8. Ciphertext the_input_enc;
  9. encryptor.encrypt(the_input_plain, the_input_enc);
  10. Plaintext const_plain_1, const_plain_2, const_plain_3;
  11. encoder.encode(3.14, scale, const_plain_1);
  12. encoder.encode(3.14, scale, const_plain_2);
  13. encoder.encode(3.14, scale, const_plain_3);
  14. Ciphertext const_cipher_1, const_cipher_2, const_cipher_3;
  15. encryptor.encrypt(const_plain_1, const_cipher_1);
  16. encryptor.encrypt(const_plain_2, const_cipher_2);
  17. encryptor.encrypt(const_plain_3, const_cipher_3);
复制代码

二、密文乘法测试

        跟上篇一样,每乘一次举行解密输出,便于查看中心效果信息。基于之前理论,继承 三次乘法,两次 Rescale。
2.1 乘法设置及密文巨细观察

先写一下乘法代码:(注意所用的乘法函数和之前差别
  1. evaluator.multiply_inplace(the_input_enc, const_cipher_1);
  2. evaluator.rescale_to_next_inplace(the_input_enc);
  3. evaluator.mod_switch_to_inplace(const_cipher_2, the_input_enc.parms_id());
  4. const_cipher_2.scale() = the_input_enc.scale();
  5. evaluator.multiply_inplace(the_input_enc, const_cipher_2);
  6. evaluator.rescale_to_next_inplace(the_input_enc);
  7. evaluator.mod_switch_to_inplace(const_cipher_3, the_input_enc.parms_id());
  8. const_cipher_3.scale() = the_input_enc.scale();
  9. evaluator.multiply_inplace(the_input_enc, const_cipher_3);
  10. decryptor.decrypt(the_input_enc, the_input_plain);
  11. encoder.decode(the_input_plain, the_input);
复制代码
先辈行两次乘法查看中心效果:(这里输出一下 密文巨细

         对比之前的明文乘法,密文巨细产生了变化,明文乘法后,巨细不变这里密文相乘后,效果的密文巨细达到了3;第二次乘法后,巨细变成了4;固然这里容量的变化比力明显,不外不知道其和巨细的具体区别。

2.2 重新线性化观察

引入重新线性化,继承观察:

        此处可以发现,每次重新线性化后,密文巨细会减小到2,但是不会改变容量。别的,末了一位的精确值是 40375.062 ,上面对第二次乘法和第二次重新线性化后都举行了解密,对比不举行重新线性化,精度并未明显增强。由于 CKKS 没有噪声预算的概念,所以重新线性化在此处,并未观察到除减小密文外,明显的其他增益效果。

三、深度 密文乘法测试

接下来,将 coeff_modulus 的长度为 4 和 5 分别举行测试。 (下面也举行了重新线性化)

3.1 长度为4的模数链

scale = 30,coeff_modulus = 160 (50 + 30 + 30 + 50) bits

果然,想举行第三次乘法,会报错:scale out of bounds!
按照上篇的理论,当处在模数链底层时,乘法效果的 scale 要小于 coeff_modulus 第一位

那更改参数为:scale = 29,coeff_modulus = 176 (59 + 29 + 29 + 59) bits

        果然就不报错,乐成举行了第三次密文乘法。但是,第二次乘法效果还近似精确,第三次效果就不精确了(第一位本应该是0的),证实此种参数设置虽然可以乘,但是精度严重不敷。

3.2 长度为 5 的模数链

既然上面的结论同上篇雷同,那同理继承拉长模数链:(为了减少冗余,只截后面乘法效果)
scale = 30,coeff_modulus = 190 (50 + 30 + 30 + 30 + 50) bits

        第三次乘法后,第三位的精确效果是:61.9183,末了一位应该是:126777.6947。可以看出,精度还可以。
别的,为了严谨,我还实验了不举行重新线性化的三次密文乘法,效果为:

        密文长度从一开始的2,增长到了5,但是解密的效果与上面近似。再次验证了重新线性化,并未带来精确度的提升。
3.3 深度乘法总结

本节的测试与上篇明文乘法的结论雷同,即:

  • 模数链限定了乘法深度(精确说是 Rescale 次数);
  • 处在模数链底的时候较为特别:注意设置 coeff_modulus 第一位大于乘后 scale;
  • 要想进步精度,就要适当拉长模数链(但是代价更大,下面会测试)。
     
四、参数设置对内存占用的影响

先叠甲:
        本节测试是统计差别参数设置,对内存占用的影响。差别性能的盘算机测试数据可能有差别,且我是用 Debug 模式运行,监视内存占用得出的数据,内存自己包含了 “上下文情况、各种密钥和实例”,乃至我每次运行都有颠簸,故不能看成精确值来推算,只具有相对意义

测试阐明:(为了减少上述因素带来的差别,故编码和加密的数目设置的比力多)
        设置模式为 CKKS方案,设置的 poly_modulus_degree = 8192,创建 二维 Plaintext 和 Ciphertext 数组。步调如下:

  • 创建 [50,50] 的 Plaintext 数组,即一共 2500 个明文块;
  • 二层循环遍历数组,依次对每块举行编码(编码内容一样,都是雷同的4096个数);
  • 编码竣事后,统计当前的 内存占用 和 程序运行时间;
  • 创建 [50,50] 的 Ciphertext 数组,即一共 2500 个密文块;
  • 二层循环遍历数组,依次对每块明文加密后放入对应密文块;
  • 加密竣事后,统计当前的 内存占用 和 程序运行时间。
        这里测试的含义是:poly_modulus_degree = 8192 时,差别参数设置下,编码 2500个 明文块,以及加密 2500 个密文块。对应能存储的数据数目为:
 。

由于测试比力无聊,这里直接上效果:(再次夸大,由于颠簸的原因,忽略小差别)

从表中发现结论:

  • 明文块的巨细 和 编码时间 相对友好,密文块巨细 和 加密的运行时间 就很浮夸了;
  • 纵向来看,调大中心值 和 scale,几乎不会影响内存占用;
  • 横向来看,加长模数链,会同时增长明文块和密文块的巨细!

        上节提到了,除了加大scale,加长模数链能进步效果精度,但是这里会加大内存。所以第三条结论比力紧张,为此再追加测试:

        证实,确实加长模数链会加大明文和密文的内存,相应的盘算时长应该也会增长(由于 编码 和 加密 时间确实长了)。别的,本次虽然只做了 CKKS 方案,但是 coeff_modulus 的设置雷同,故其他方案的结论应该也类似。

五、本篇总结

        本篇继承上篇针对 CKKS 方案的测试,首先证实白 重新线性化 虽然会减少密文长度,但是并不会对 盘算效果的精度 有明显的影响模数链的长度确实会限定乘法深度(具体来说是 Rescale 次数),这点上密文乘法和明文乘法雷同
        上篇中证实白 增长 scale 会进步精度,本篇也继承证实白 增长模数链 也能增长精度,但是内存测试后,前者 scale 不会进步内存,后者会增长 内存本钱 和 时间本钱。
        总结会发现,在应用同态加密的时候,首先 乘法深度很是受限,其次 内存本钱 和 时间本钱都是很需要考量的。故在操持算法的时候,要综合思量多方面因素,还是比力费工夫的。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

花瓣小跑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表