同态加密和SEAL库的介绍(十)CKKS 参数心得 2
写在前面:
本篇继续上篇的测试,首先针对密文深度乘法情况,虽然密文乘法本就是应该尽量避免的(时间和内存成本过高),更不用说深度乘法了,但是为了测试的完整性,还是做一下方便大家比对。
其次是关于参数设置对内存占用的影响,这个十分重要,因为我们在跑模型的时候,经常进程被 kill,因为确实是密文出乎意料的大,后面根据测试数据大家就能看出来。
一、测试配置
因为和之前的设置一样,这里就不多介绍了,直接放代码。
1.1 前置设置
EncryptionParameters parms(scheme_type::ckks);
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 50, 30, 30, 50 }));
double scale = pow(2.0, 30);
SEALContext context(parms);KeyGenerator keygen(context);
auto secret_key = keygen.secret_key();
PublicKey public_key;
keygen.create_public_key(public_key);
RelinKeys relin_keys;
keygen.create_relin_keys(relin_keys);
GaloisKeys gal_keys;
keygen.create_galois_keys(gal_keys);
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
CKKSEncoder encoder(context);
size_t slot_count = encoder.slot_count();
1.2 输入设置
为了具有对比参考价值,这里输入也设置成一样,不过对三个乘数进行加密。
vector<double> the_input;
the_input.reserve(slot_count);
for (size_t i = 0; i < slot_count; i++){the_input.push_back((double)i);
}
Plaintext the_input_plain;
encoder.encode(the_input, scale, the_input_plain);
Ciphertext the_input_enc;
encryptor.encrypt(the_input_plain, the_input_enc);Plaintext const_plain_1, const_plain_2, const_plain_3;
encoder.encode(3.14, scale, const_plain_1);
encoder.encode(3.14, scale, const_plain_2);
encoder.encode(3.14, scale, const_plain_3);
Ciphertext const_cipher_1, const_cipher_2, const_cipher_3;
encryptor.encrypt(const_plain_1, const_cipher_1);
encryptor.encrypt(const_plain_2, const_cipher_2);
encryptor.encrypt(const_plain_3, const_cipher_3);
二、密文乘法测试
跟上篇一样,每乘一次进行解密输出,便于查看中间结果信息。基于之前理论,继续 三次乘法,两次 Rescale。
2.1 乘法设置及密文大小观察
先写一下乘法代码:(注意所用的乘法函数和之前不同)
evaluator.multiply_inplace(the_input_enc, const_cipher_1);
evaluator.rescale_to_next_inplace(the_input_enc);evaluator.mod_switch_to_inplace(const_cipher_2, the_input_enc.parms_id());
const_cipher_2.scale() = the_input_enc.scale();
evaluator.multiply_inplace(the_input_enc, const_cipher_2);evaluator.rescale_to_next_inplace(the_input_enc);evaluator.mod_switch_to_inplace(const_cipher_3, the_input_enc.parms_id());
const_cipher_3.scale() = the_input_enc.scale();
evaluator.multiply_inplace(the_input_enc, const_cipher_3);decryptor.decrypt(the_input_enc, the_input_plain);
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 不会提高内存,后者会增加 内存成本 和 时间成本。
总结会发现,在应用同态加密的时候,首先 乘法深度很是受限,其次 内存成本 和 时间成本都是很需要考量的。故在设计算法的时候,要综合考虑多方面因素,还是比较费工夫的。
相关文章:

同态加密和SEAL库的介绍(十)CKKS 参数心得 2
写在前面: 本篇继续上篇的测试,首先针对密文深度乘法情况,虽然密文乘法本就是应该尽量避免的(时间和内存成本过高),更不用说深度乘法了,但是为了测试的完整性,还是做一下方便大家比对…...

Debug-021-el-table实现分页多选的效果(切换分页,仍可以保持前一页的选中效果)
前情提要: 这个功能实现很久了,但是一直没有留意如何实现,今天想分享一下。具体就是我们展示table数据的时候,表格中的数据多数情况是分页展示,毕竟数据量太多,分页的确是有必要的。那么我们有业务需要给表…...

FPGA开发——DS18B20读取温度并且在数码管上显示
一、简介 在上一篇文章中我们对于DS18B20的相关理论进行了详细的解释,同时也对怎样使用DS18B20进行了一个简单的叙述。在这篇文章我们通过工程来实现DS18B20的温度读取并且实现在数码管伤显示。 1、基本实现思路 根据不同时刻的操作,我们可以使用一个状…...

电流测量分流电阻
电流测量分流电阻 测量电流的设备称为安培计。大多数现代安培计测量已知电阻的精密电阻上的电压降。电流的计算使用欧姆定律:我五R 大多数电流表都内置电阻器来测量电流。但是,当电流对于电流表来说太高时,需要不同的设置。解决方案是将电流…...

MES系统:智能化排班排产的全面解决方案
MES(制造执行系统)管理系统通过集成多种先进技术、实时数据采集与分析、优化算法应用以及与其他系统的协同工作,实现了智能化排班排产功能。以下是该功能的详细实现方式: 数据集成与实时采集:MES系统与ERP、SCM、设备管…...

50道深度NLP和人工智能领域面试题+答案
编者按:分享一个很硬核的免费人工智能学习网站,通俗易懂,风趣幽默, 可以当故事来看,轻松学习。 什么是自然语言处理(NLP)?自然语言处理是一种人工智能领域,致力于使计算机…...

最小矩阵宽度(85%用例)C卷(JavaPythonC++Node.jsC语言)
给定一个矩阵,包含N*M个整数,和一个包含K个整数的数组。 现在要求在这个矩阵中找一个宽度最小的子矩阵,要求子矩阵包含数组中所有的整数。 输入描述: 第一行输入两个正整数N,M,表示矩阵大小。 接下来N行M列表示矩阵内容。 下一行包含一个正整数K。 下一行包含K个整数,…...

STM32数据按字符截取与转换
目录 1. 截取2. 转换 1. 截取 以SW,33,55,78,\r\n为例 char* pa,pb,pc,pd,pe; uint8_t usart5_rxsavebuf[] "SW,12,32,33,55,78,\r\n";strtok((char *)usart5_rxsavebuf, ","); pa strtok(NULL, ","); pb strtok(NULL, ","); pc …...

使用kubeadm快速部署一套K8S集群
一、Kubernetes概述 1.1 Kubernetes是什么 Kubernetes是Google在2014年开源的一个容器集群管理系统,Kubernetes简称K8S。 K8S用于容器化应用程序的部署,扩展和管理。 K8S提供了容器编排,资源调度,弹性伸缩,部署管理…...

【Kotlin】在Kotlin项目中使用AspectJ
前言 AOP编程在Java开发中是一个非常火热的话题,最著名的库为AspectJ Kotlin项目中,通过Gradle插件,也能够使用该库,这是我们下面讲解的重点 由于AspectJ的原理是在预编译阶段,通过插件修改代码,生成代理…...

web实现drag拖拽布局
这种拖拽布局功能其实在电脑操作系统或者桌面应用里面是经常使用的基础功能,只是有时候在进行web开发的时候,对这个功能需求量不够明显,但却是很好用,也很实用。能够让用户自己拖拽布局,方便查看某个区域更多内容&…...

Linux网络编程—listen、accept、connect
一、网络四件套 #include <sys/types.h> //头文件;这四个文件一包,基本网络就无问题了; #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> 二、listen 监听:将套…...

logback.xml自定义标签节点
logback.xml自定义标签节点 问题 <?xml version"1.0" encoding"UTF-8" ?> <configuration scan"true" scanPeriod"60 seconds" debug"false"><appender name"console" class"ch.qos.logb…...

探索DevExpress WinForms:.NET世界中的UI库之星
开篇概述 作为一名资深的技术专家,我对.NET开发和UI库有着深入的了解。今天,我要向您介绍的是DevExpress WinForms —— 一款在.NET开发领域广受欢迎的开源UI库。它以其强大的功能、优雅的设计和卓越的性能,成为了众多开发者的首选。 主体讲解…...

零基础学习Redis(4) -- 常用数据结构介绍
我们之前提到过,redis中key只能是字符串类型,而value有多种类型。 redis中的数据结构有自己独特的实现方式能根据特定的场景进行优化 1. string(字符串) 内部编码: raw:最基本的字符串,类比我们平常使用的Stringin…...

Python实现水果忍者(开源)
一、整体介绍: 1.1 前言: 游戏代码基于Python制作经典游戏案例-水果忍者做出一些改动,优化并增加了一些功能。作为自己Python阶段学习的结束作品,文章最后有源码链接。 1.2 Python主要知识: (1…...

Windows自动化3️⃣WindowsPC拽起时长问题解决方案
问题描述: Windows应用从点击, 到加载完成, 需要一定的时间后台是否已经启动过当前程序?启动后, 前后台应用关闭问题等 我的解决思路: 首先检查进程 , 当前进程是否在运行, 如果进程在运行, 需要先关闭进程 关闭进程后, 开始我们的自动化流程, 去拽起 应用 拽起应用后, 可以先…...

一篇文章入门Java虚拟机(JVM)
JVM全称是Java Virtual Machine,中文译名Java虚拟机。本质上是一个运行在计算机上的程序 一,JVM的功能 功能描述解释和运行对字节码文件中的指令,实时的解释成机器码,让计算机执行内存管理自动为对象、方法等分配内存࿱…...

vue3里面的组件实例类型(包括原生的html标签类型)
在 通过 ref(null)获取组件的时候,我们想要为 组件标注组件类型,可以通过 any 类型来进行标注,但是很明显,这些的代码很不优雅,所以我们可以利用 vue3 里面的 InstanceType 来进行类型标注 这是…...

谷歌正式开放Imagen 3访问权限!OpenAI的GPT-4o连续两周迎来两次更新!|AI日报
文章推荐 马斯克Grok 2打响反内容限制第一枪,盛大网络狂欢!一起来看网友花式整活! GPT-4o一天迎来2大劲敌!Grok-2发布测试版!Gemini Live即刻上线! 今日热点 OpenAI发布chatgpt-4o-latest AI模型&#…...

C语言内存操作函数
目录 一. C语言内存操作函数 1. memcpy的使用和模拟实现 2. memmove函数 3. memset函数 4. memcmp函数 一. C语言内存操作函数 随着知识的不断积累,我们所想要实现的目标程序就会更加复杂,今天我们来学习一个新的知识叫做C语言内存操作函数&#x…...

深入探索 PyTorch:torch.nn.Parameter 与 torch.Tensor 的奥秘
标题:深入探索 PyTorch:torch.nn.Parameter 与 torch.Tensor 的奥秘 在深度学习的世界里,PyTorch 以其灵活性和易用性成为了众多研究者和开发者的首选框架。然而,即使是经验丰富的 PyTorch 用户,也可能对 torch.nn.Pa…...

成为Python砖家(1): 在本地查询Python HTML文档
目的 Python3 官方文档位于 https://docs.python.org/3/ , 有时候网络无法连接,或者连接速度慢, 这对于学习 Python 时的反馈造成了负面影响。准备一份本地 Python 文档可以让反馈更加及时。 下面给出 macOS 和 Win11 下的 Python 离线文档…...

深度学习基础—RMSprop算法与Adam 优化算法
1.RMSprop算法 1.1.算法流程 除了动量梯度下降法,RMSprop算法也可以加快梯度下降,这个算法的算法流程如下:深度学习基础—动量梯度下降法http://t.csdnimg.cn/zeGRo 1.2.算法原理 和动量梯度下降不同的是,对dW和db的变成了平方项…...

单片机原理及技术(六)—— 中断系统的工作原理
目录 一、AT89S51中断技术概述 二、AT89S51中断系统结构 2.1 中断请求源 2.2 中断请求标志寄存器 2.2.1 TCON 寄存器 2.2.2 SCON 寄存器 三、中断允许与中断优先级的控制 3.1 中断允许寄存器 IE 3.2 中断优先级寄存器 IP 四、响应中断请求的条件 五、外部中断的触发…...

Angular路由使用
Angular路由是Angular框架中一个非常重要的特性,开发者可以根据URL的不同来动态地加载和显示不同的组件,从而构建出单页面应用(SPA)。 以下是Angular路由使用的基本步骤和要点: 1. 安装和配置路由模块 首先…...

【JVM】深入理解类加载机制(一)
深入理解类加载机制 Klass模型 Java的每个类,在JVM中都有一个对应的Klass类实例与之对应,存储类的元信息如:常量池、属性信息、方法信息…从继承关系上也能看出来,类的元信息是存储在元空间的。普通的Java类在JVM中对应的是InstanceKlass(C)…...

区块链浏览器需求整理
用户需求 普通用户 便捷查询交易记录:能够轻松找到自己或特定地址的交易详情,包括交易时间、金额、状态等。查看账户余额:实时了解地址的余额情况。追踪资产流向:了解自己的资产在区块链上的转移路径。 开发者 智能合约调试&a…...

Laravel 表单验证功能重定向判断
判断主要针对 API 请求和普通页面请求,即 API 的表单验证失败直接响应 JSON,而页面的表单验证失败正常重定向。 看网上基本上是继承 FormRequest 类来实现,其实直接修改异常处理的 Handler 类即可,非常简单。 打开 app/Exception…...

MATLAB口罩检测系统
一、应用背景 作为数字图像处理和计算机视觉领域的一个重要组成部分,利用摄像机对图像进行采集,从图像中检测人脸并进行口罩穿戴的识别的有着非常重要的研究意义和应用价值。面对突如其来的新型肺炎疫情,人们生活秩序被严重打乱。跟普通流感…...