本篇会对比三种加密方案,同时每种方案配置三种参数。即九种情况下的各个操作的性能差异,为大家选择合适的方案和合适的参数提供参考。表格中所有时长的单位均为微妙,即 。
当然数据量比较大,为了方便大家查找,按照不同级别标题进行了区分,便于跳转。
注意:
本篇所写的测试数据,仅具有相对意义(即不同性能的计算机跑出来时长有差异),不能简单的作为衡量标准。同时,不同的加密参数导致的性能差异较大,加密的数据不同也会影响操作的性能,所以具体情况还是要自己进行实验。
示例中所有操作,均为执行了十次后取的平均值。并且主要会对比不同方案,不同 poly_modulus_degree 下的性能差异,但是 coeff_modulus 的设置也是适当匹配 poly_modulus_degree 大小的。即不同参数设置差异较大,变量不是唯一的。
一、加密参数展示
1.1 三种 BFV 方案参数
1.2 三种 BGV 方案参数
1.3 三种 CKKS 方案参数
二、产生密钥效能对比
不同例子中,密钥产生的时长首先是需要考虑的。尤其是Galois密钥,可能会占用大量内存,这在受限系统中可能是个问题,应该尝试一些更大的测试运行,并观察它们对内存池分配大小的影响。
下面比较时长差异较大的 relinearization keys 和 Galois keys。
2.1 relinearization keys
| 4096 | 8192 | 16384 |
BFV | 22359 | 131629 | 880082 |
BGV | 24174 | 144649 | 977182 |
CKKS | 23205 | 135087 | 893252 |
2.2 Galois keys
| 4096 | 8192 | 16384 |
BFV | 471257 | 3229431 | 23322354 |
BGV | 517306 | 3592576 | 25117895 |
CKKS | 478956 | 3142806 | 23158120 |
三、编解码
编码这里 BFV 和 BGV 采用的都是 Batch Encoder,CKKS采用的是CKKSEncoder。
3.1 编码
| 4096 | 8192 | 16384 |
BFV | 562 | 1198 | 2513 |
BGV | 551 | 1226 | 2687 |
CKKS | 3970 | 11097 | 35688 |
3.2 解码
| 4096 | 8192 | 16384 |
BFV | 694 | 1217 | 2591 |
BGV | 604 | 1219 | 2683 |
CKKS | 6840 | 23391 | 86703 |
四、加解密
4.1 加密
| 4096 | 8192 | 16384 |
BFV | 28807 | 90978 | 325499 |
BGV | 33401 | 111285 | 398689 |
CKKS | 26394 | 82988 | 297074 |
4.2 解密
| 4096 | 8192 | 16384 |
BFV | 8155 | 28594 | 111851 |
BGV | 5887 | 21645 | 83201 |
CKKS | 2234 | 8185 | 34076 |
五、加法
加法这里只统计了密文加密文的加法函数,因为和明文加密文函数的差异不大,并且和乘法相比,加法时间更短,也基本没有噪声损失。故选择算法时,尽量用加法来减少乘法次数。
| 4096 | 8192 | 16384 |
BFV | 1907 | 7648 | 31280 |
BGV | 1992 | 7760 | 30592 |
CKKS | 1976 | 7850 | 30895 |
六、乘法
5.1 明文乘密文
| 4096 | 8192 | 16384 |
BFV | 7859 | 32869 | 142946 |
BGV | 3970 | 15894 | 63479 |
CKKS | 2254 | 8668 | 34371 |
5.2 密文乘密文
| 4096 | 8192 | 16384 |
BFV | 105631 | 392150 | 1626688 |
BGV | 5489 | 21526 | 85366 |
CKKS | 5420 | 21829 | 86503 |
5.3 平方
| 4096 | 8192 | 16384 |
BFV | 73187 | 272906 | 1137618 |
BGV | 4646 | 17319 | 68582 |
CKKS | 4342 | 17133 | 68566 |
七、旋转
6.1 行旋转 - 一步
| 4096 | 8192 | 16384 |
BFV | 21078 | 111939 | 718794 |
BGV | 28039 | 138755 | 791834 |
CKKS | 22252 | 117407 | 726842 |
6.2 行旋转 - 随机步长
这里用随机函数,生成一个步数,旋转记录时长,即十次旋转的都不同,最后取平均。当然只是为了比对单步的行旋转,说明多步需要更多的时间。
| 4096 | 8192 | 16384 |
BFV | 86387 | 390785 | 2855098 |
BGV | 116092 | 536996 | 3550023 |
CKKS | 83390 | 517397 | 3339613 |
6.3 列旋转
| 4096 | 8192 | 16384 |
BFV | 21112 | 390785 | 2855098 |
BGV | 27963 | 137158 | 789150 |
八、重新线性化
| 4096 | 8192 | 16384 |
BFV | 21106 | 111579 | 715234 |
BGV | 27121 | 134387 | 775288 |
CKKS | 21871 | 115797 | 726314 |
九、Rescale
因为 rescale 操作只在CKKS方案中进行,这里虽然不比较,但是列出来供大家参考:
| 4096 | 8192 | 16384 |
CKKS | 3713 | 19017 | 79439 |
十、总结
这里简单总结几点我发现的规律:
- 同一方案下,操作的时长并不是跟着 poly_modulus_degree 的倍数,成倍数增长,故槽的数量大了,虽然一次能处理的数据更多,时间代价会更大;
- CKKS 和 BFV 方案相比,编解码时间长了,但是乘法时间更短,尤其是密文乘密文;
- 直接旋转 n步长 的时间是快于一次转一个转 n次的;
- 密文乘密文 的时间成本要明显大于 明文乘密文,故尽量采用明文乘法;
- 重新线性化的时间成本并不低,虽然减少了密文长度,但是其代价也是要纳入考量的;
- 这里的参数大小配置是相适应的,但是要想获得最优性能,还是应该根据自己的数据和算法,定制一个合理的噪声预算和算法顺序。
总结就是,用同态加密实现功能不难,但是在保证正确性的前提下提高效能是个要具体情况具体设计的问题,需要花功夫花时间取钻研的。