【FHE 同态加密】我们如何实现同态加密推理(七):自举 Bootstrapping——一个不提高精度、只刷新模数链的“加油站“

简介: 本文揭秘FHE自举(Bootstrapping)本质:它并非纠错或提精度,而是“模数链加油站”——通过七段流水线(含coeff_to_slot/slot_to_coeff等)刷新链长,误差几乎不变(1.2712e-03→1.2706e-03)。实测80%耗时集中于两次域变换,项目开源可复现。

【FHE 同态加密】我们如何实现同态加密推理(七):自举 Bootstrapping——一个不提高精度、只刷新模数链的"加油站"

关键词:同态加密 | FHE | 自举 | Bootstrapping | 模数链刷新 | coeff_to_slot | slot_to_coeff | EvalMod | 大模型密文推理

导读:自举(Bootstrapping)在同态加密里常被误解成"纠错"或"提精度"。本篇用实测数字说明它其实只是一个"加油站":把被乘法吃掉的模数链还给同态加密推理引擎,精度几乎不动。内容包含七段流水线、sin 折叠(EvalMod),以及 80% 时间花在哪两段域变换上。

项目仓库
Gitee 主仓:https://gitee.com/pei-xiaoguang/kestrel-llm
GitHub 镜像:https://github.com/m13253246268-ship-it/kestrel-llm

相关文档
术语与数据口径 |
性能与基准 |
构建与复现 |
快速上手 |
架构总览

0. 一句话结论

自举(bootstrapping)不提高精度,它只做一件事:把被乘法吃掉的模数链还给你。

实测证据很干净——同一层的结果,自举前后与明文参考的误差几乎不动:

对象 链长 `max err `
u0(lay0 产出) np=16 1.2712e-03
u0r112(boot0 刷新后) np=112 1.2706e-03

链长从 16 回到 112,误差从 1.2712e-03 变成 1.2706e-03。

如果你把自举理解成"纠错"或"提精度",那这个数字会让你困惑;把它理解成"加油"就通了——油加满了,车并没有变快。


1. 为什么必须自举

CKKS 的每一次乘法都要 rescale,而 rescale 会切掉一个素数(本系列第 5 篇)。链长是单向消耗的。

一跳的实际数字:

阶段 链长
输入 112
lay 消费后 16
boot 刷新后 112

16 这个数字意味着"还能再算十几步乘法"——对于一个 28 层的模型,这远远不够。自举就是那个周期性的补给站。


2. 七段流水线(实测顺序)

驱动 t23_chain.c 的 [boot profile] 打印把整条自举摊开了,字段顺序就是执行顺序:

modraise → coeff_to_slot → rotate_k → conj_extract
        → sin_fold_re / sin_fold_im → restore_merge → slot_to_coeff
# 段 做什么 对应函数
1 modraise 用 Garner 扩展把链抬回满链 ckks_modraise()
2 coeff_to_slot 系数域 → 槽位域 coeff_to_slot()
3 rotate_k Galois 旋转 ckks_rotate_k()
4 conj_extract 共轭提取:分出实部/虚部 —
5 sin_fold_re / _im 对实部、虚部分别做 sin 折叠 sin_fold()
6 restore_merge 还原并合并 —
7 slot_to_coeff 槽位域 → 系数域 slot_to_coeff()

在这里插入图片描述

图 7-1 怎么读:左列是域——modraise 在系数域上做,coeff_to_slot 与 slot_to_coeff 是两次跨域搬运,中间四段都在槽位域上逐点操作;右侧条形按实测耗时成比例,两根红框的条形(coeff_to_slot + slot_to_coeff)合起来就是那 80%。图中只画了正文 §4 给出的三个量,其余四段合计 ≈31 s,未逐段展开。

矢量版 figs/fig07_bootstrap_pipeline.svg|Graphviz 源码 figs/fig07_bootstrap_pipeline.dot

这个顺序本身就是答案:自举的本质是"把消息从槽位域搬到系数域,做一次取模(modular reduction),再搬回槽位域"。难点全在"搬"上。


3. 为什么要"搬":EvalMod 与 sin 折叠

在槽位域里,一个槽位装的是一个近似的实数(scale = 2^60 定标)。你想对它做"取模 q"这种操作,直接做不了——因为取模是在系数域上才有意义的整数操作。

于是标准做法是:

  1. modraise:把模数从当前的短链,用 Garner 扩展抬回满链。这一步把"模数空间"还给消息;
  2. coeff_to_slot:把消息从槽位域变回系数域,此时那个"需要取模的量"变成了系数的整数倍;
  3. sin_fold:用 sin 的周期性(sin(πx) 型的倍角/折叠结构)来逼近那个取模函数。因为取模在数学上可以写成锯齿波,而锯齿波可以用 sin 的倍角多项式逼近;
  4. slot_to_coeff / restore_merge:搬回去。

rotate_k 与 conj_extract 的存在,是因为"实部/虚部"要分开处理——复数的实虚部在系数域里纠缠在一起,需要用 Galois 自同构与共轭把它们分离出来,各自折叠,再合并回去。

3.1 为什么是把私钥稀疏度降到 8

一个不显然的取舍(头注释原文):

降 hw 控制 bootstrapping 折叠混叠:混叠 I ~ hw/2 = 4,sin 逼近多项式 9 次;原型无安全可接受。

hw 是私钥的非零系数个数,这代被设成 8(CKKS_KEY_HW)。它不是随手取的:私钥越稀疏,sin 折叠时产生的混叠(aliasing)越小(约 hw/2 = 4),于是只需要 9 次多项式就能逼近到位。

换句话说:为了自举的数值可行性,我们主动牺牲了密码学参数(hw 越小越不安全)。作者在注释里明确标注了"原型无安全可接受"——这个取舍如果我们不写出来,读者会以为 hw=8 是某种安全选择。


4. 自举的代价:80% 的时间花在"搬"

boot0 的实测分段(字段名与上文七段一一对应):

段 耗时 占比
coeff_to_slot 1688 s ~39%
slot_to_coeff 1716 s ~40%
sin_fold(实部+虚部) ~850 s ~20%
modraise / rotate_k / conj_extract / restore_merge 其余 余下
total 4285.03 s 100%

两个"域变换"加起来约 3400 s,占 80%。

这个结果直接否掉了我们的第一版优化直觉——"去优化多项式乘法"。乘法(NTT)确实是最热的内核,但在这条链上,时间不在卷积里,在域变换里:coeff_to_slot 与 slot_to_coeff 每段都要做大量的 Galois 旋转和 key-switch(本系列第 6 篇那对 3×2 个密钥就是在这里被反复使用的)。

顺带对比:同一轮的 lay0 是 1920 s,而 boot0 是 4285 s。一层 1.8 小时里,有约 1.2 小时花在自举上。


5. 一个工程细节:懒初始化的并发陷阱

代码里留了一条修复记录(t23_chain.c 附近):

tab_prepare(n);   /* M1c 修复:coeff_to_slot/slot_to_coeff 的 omp 区并发首次触发 ... */

含义是:某些预计算表原来是在并行区里首次访问时懒初始化的。多线程同时"第一次"进入,就会并发触发初始化——这是经典的隐蔽竞态。修法是在进并行区之前显式 tab_prepare。

这类 bug 的特点是:单线程永远不出现,多线程偶发。它跟本系列第 13 篇(位级可复现性)是同一类问题的两个面。


6. 安全边界(务请读完)

本文所述参数为机制验证级(n=2048、112/2100 素数链),
远低于 HE 参数标准的 128-bit 水平,不得用于保护真实数据。
本文主张的是:自举流水线的结构与实测账本。
本文不主张:安全强度、性能优越性。

特别提醒:§3.1 的 hw=8 是为数值可行性做的妥协,不是安全选择。请勿把本文任何参数当成可用的密码学配置。


7. 这一篇的未解问题

  1. coeff_to_slot / slot_to_coeff 为什么这么贵,我们没有逐段归因。是旋转次数多?是 key-switch 的密钥太大导致缓存不友好?还是 NTT 调用次数过多?目前只有总量,没有分解。这是本项目最值得做的一块性能分析,也是收益最大的一块。
  2. hw=8 与精度之间的关系没有量化。我们知道 hw 小→混叠小→多项式次数低,但"hw 从 8 提到 16 会坏多少、慢多少"没有测。
  3. 自举的链长余量没有探边。t23boot 编到 2100 素数;实际用到多少、还能压到多低,我们没有做"最小可用链长"的扫描。而链长直接决定内存与耗时。
  4. sin_fold 的精度贡献与误差来源没有分离。我们只知道整链误差,不知道折叠这一步贡献了多少。

下一篇我们回到模型侧:SiLU 的密文化——两条拟合路径,以及那个只有 8 字节、却能让你算出错误答案的开关文件。

相关文章
|
4天前
|
安全 调度 数据安全/隐私保护
【FHE 同态加密】我们如何实现同态加密推理(一):把 2B 大模型拆成 28 段密文链条来算(纯 C11 · 零依赖)
本系列记录纯C11、零依赖、CPU-only实现2B大模型(Qwen3-VL-2B)全密文推理的全过程:将模型拆为28段可验证密文链,每跳约1.8小时,聚焦可复现性与机制验证,非安全级部署。(239字)
|
5天前
|
存储 缓存 编解码
0.8MB 跑通 Qwen|第 19-2 篇:推理引擎的 vision_tokens 客户端预编码协议
本系列《0.8MB跑通Qwen》专注手搓零依赖纯C推理引擎,适配Qwen3-VL多模态大模型,在RK3588(aarch64)实测通过。本文详解`encode_media_item`三路协议:`image_url`(板端ViT+128位缓存)、`video_frames`(帧序列)与`vision_tokens`(客户端预编码跳过ViT),支持字节数自校验与缓存命中优化,真机实测ViT耗时295ms→缓存后仅301ms。
|
5天前
|
编解码 算法 C++
0.8MB 跑通 Qwen|第 17-3 篇:位级一致性实验——推理引擎两条转换路产物逐字节对拍
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎实现,实测RK3588上位级一致性验证:同源重跑确定性、无损源跨格式殊途同归、有损源再量化边界清晰可测。覆盖Qwen3-VL多模型,强调sha256/逐张量哈希/块级比对三位一体验证。(239字)
|
3天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型深度拆解:原理解读、实战测评与保姆级落地教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为**System One Model(系统一模型)**,对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
249 1
|
6天前
|
编译器 C语言
0.8MB 跑通 Qwen|第 2-1 篇:推理引擎的 C11 `_Static_assert`——让编译器守卫你的内存布局
本文详解C11 `_Static_assert` 在内存布局守卫中的关键作用:针对mmap直挂场景,通过编译期断言钉死VQF格式三结构体(200/432/64字节),杜绝因对齐差异导致的静默错位。真机RK3588实测验证,实现错误前移。
0.8MB 跑通 Qwen|第 2-1 篇:推理引擎的 C11 `_Static_assert`——让编译器守卫你的内存布局
|
6天前
|
芯片 AI芯片
0.8MB 跑通 Qwen|第 2-3 篇:推理引擎的设备画像——识别 RK3588,而不是"猜"(vllm_device.c)
本文实测RK3588设备画像机制:通过启发式匹配`/proc/device-tree/model`识别板型,自动生成含NPU支持、量化推荐等配置的`VDevProfile`;支持`--device`人工覆盖,验证画像如何精准驱动引擎决策。(239字)
 0.8MB 跑通 Qwen|第 2-3 篇:推理引擎的设备画像——识别 RK3588,而不是"猜"(vllm_device.c)
|
2天前
|
安全 数据安全/隐私保护 C++
【FHE 同态加密】我们如何实现同态加密推理(六):Key-Switch 重线性化——一个数量级(2^73 噪声)决定整个设计
本文深入解析CKKS同态加密中Key-Switch(重线性化)的核心设计逻辑:关键在于噪声数量级——未分解时引入约2⁷³噪声,远超60-bit模数容限;采用base-2²⁰数字分解降至2⁴⁵,方保安全。由此决定relin密钥需3×2个多项式,并延伸至Galois旋转密钥结构。(239字)
|
4天前
|
机器学习/深度学习 安全 数据安全/隐私保护
【FHE 同态加密】我们如何实现同态加密推理(四):为什么我们最终放弃了 BFV——明文模上的除法如何逼死 GELU(纯 C11 · 零依赖)
本文探讨同态加密大模型推理的方案选型:BFV因明文模环不支持非整数系数(如GELU/SiLU多项式),难以适配实数神经网络;CKKS凭借scale机制与模数切换,实现可控近似计算,成为更优选择。(239字)
|
6天前
|
缓存 测试技术 C语言
0.8MB 跑通 Qwen|第 1-3 篇:推理引擎的自检门——没有模型的确定性测试,第一次读懂 PASS/FAIL
本文介绍RK3588平台LLM推理引擎的“自检门”机制:无需模型文件,通过标量参考对拍、固定种子随机与确定性PASS/FAIL测试,快速验证编译后代码正确性;实测覆盖L3缓存、量化点积等核心逻辑,体现工业级可信验证思想。(239字)
 0.8MB 跑通 Qwen|第 1-3 篇:推理引擎的自检门——没有模型的确定性测试,第一次读懂 PASS/FAIL
|
3天前
|
缓存 安全 数据安全/隐私保护
【FHE 同态加密】我们如何实现同态加密推理(五):RNS-CKKS 的模数链管理——rescale、modswitch、modraise 到底谁是谁
本文详解RNS-CKKS模数链三大核心操作:`rescale`(切素数+归一缩放)、`modswitch`(仅降模)、`modraise`(Garner上提),厘清易混语义;阐明60-bit素数选择及`q_i ≡ 1 (mod 2n)`的数学硬约束,直指大模型密文推理的精度与可行性边界。(239字)