【FHE 同态加密】我们如何实现同态加密推理(二):引擎全景——一次密态推理的完整数据流(明文 Python × 密文 C11)

简介: 这是一套面向大模型的同态加密推理引擎(FHE),采用CKKS方案,实现“明文预处理(Python)+ 密文计算(纯C11)”双世界架构:明文侧负责权重导出、非线性拟合与参考值生成;密文侧仅加载产物,在密态下完成全前向推理,保障数据“可算不可见”。

关键词:同态加密推理 | FHE | 引擎全景 | 数据流 | 密文计算 | 明文预处理 | CKKS | 纯 C11 | 大模型推理

导读:这是一套同态加密推理引擎的完整数据流全景。整套系统被一条线劈成两个世界:明文侧(Python)负责权重导出、非线性函数逼近与明文参考值,密文侧(纯 C11)只读这些产物、在大模型的密文上把前向跑完。本篇讲清这条同态加密推理链路的分界线、各层职责,以及"哪一侧该信谁"。

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

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

0. 一句话结论

整套系统被一条线劈成两个世界:

  • 明文侧(Python):把模型权重、非线性函数的逼近系数、以及"正确答案"(明文参考)算出来,落成 .bin;
  • 密文侧(纯 C):只读这些 .bin,在密文上把前向跑完,产出密文。

分界线是两样东西:拟合系数与明文参考。 密文侧从不重新拟合任何东西,明文侧从不碰密文——这个切法让两侧可以独立验证。


1. 两个世界的产物对照

明文侧(tools/preproc/,Python) 密文侧(src/core/ + 驱动,C)
输入 model.safetensors(约 4.26 GB) 明文侧落下的 .bin + 密文
产出 权重、拟合系数、明文参考值、尺度表 密文(.ct)+ 日志
依赖 numpy、safetensors 仅 libc + libm
是否可重跑 可,且产出逐字节可复现 可,且产出位级可复现(需固定线程数)
怎么验 与分发物比对哈希 verify_layer 独立解密复核

2. 明文侧:四个阶段,24 个脚本

tools/preproc/ 下是 24 个 Python 脚本,按职责分四组(完整执行顺序以 tools/preproc/README.md 的「执行顺序」一节为准):

① 导出

  • _export_weights.py:权重导出(tail/w0..w27/,每层 9 个文件)
  • _embed4.py:lay0 的明文输入——按 token id 从 embedding 表取 4 行(l0/embed4.bin,4×2048 float32,32768 B)

② 定路径

  • _silu_mode.py:逐层写出 8 字节的 tail/silu{L}.bin,决定该层的 SiLU 走"直接拟合"还是"÷21 折叠"(本系列第 8 篇专门讲这个开关,它也是最危险的一个文件)

③ 生成参考值("正确答案")

  • _full_layers.py:L0..L25 的明文因果前向参考
  • _tail_ref.py:链尾(L26..L27)参考
  • 以及 _ln_fit*.py / _m2c* / _refit_lnq.py 等:LayerNorm 与倒数之类的分支参考

④ 拟合与定标

  • _sin_fit*.py / _cos_fit.py / _recip_fit.py / _attn_fit.py:把非线性函数(sin、cos、倒数、exp)拟合成多项式,直接生成 C 数组(例如 EXP_Q[7]、RECIP_Q[9])
  • _fold_fit.py / _fold_sim.py / _cfold_plan.py:折叠方案的设计与仿真
  • _adap_scale.py:逐层尺度自适应(本系列第 9 篇)
  • _silu_err.py / _logits_tol.py:误差与容差评估工具

一个反直觉的事实:这些脚本产出的数据包约 7 GB,但它不随仓库分发。任何人都能用同一个模型把整包重新生成出来——我们核对过生成物与分发物逐字节相同。


3. 密文侧:四层职责

┌──────────────────────────────────────────────┐
│ 驱动 t23_m3p.c (lay) / t23_chain.c (boot)     │  ← 一个"层"的业务逻辑
├──────────────────────────────────────────────┤
│ vllm_ckks.c    RNS-CKKS:编码/加密/加乘/       │  ← 密文语义
│                rescale/relin/rotate/modraise  │
├──────────────────────────────────────────────┤
│ vllm_ntt.c     负循环 NTT(多项式乘法)        │  ← 数学原语
│ vllm_tp.c      自研线程池(替换 OpenMP)       │  ← 并行原语
└──────────────────────────────────────────────┘

关键点:下层不知道上层在算什么。NTT 不知道自己在做 attention,CKKS 不知道自己在算 Transformer。这条分层让"位级可验证"成为可能——你可以单独证明 NTT 是对的(与教科书 O(n²) 位级对照),而不用先信任整个模型。


4. 一跳内部发生了什么

4.1 lay(层内前向)

layL: u(L-1)r112 → uL,一串同态算子的组合:QKV 投影、attention、FFN、以及需要密文化的非线性(SiLU、倒数、exp 等,全部用预先拟合好的多项式代替)。

4.2 boot(自举刷新)

bootL: uL → u(L)r112。驱动 t23_chain.c 的 [boot profile] 打印把整条流水线摊开了,实测的七段是:

modraise → coeff_to_slot → rotate_k → conj_extract
        → sin_fold_re / sin_fold_im → restore_merge → slot_to_coeff
段 作用
modraise 用 Garner 扩展把模数链抬回满链(自举的起点)
coeff_to_slot 系数域 → 槽位域(Galois 旋转 + key-switch)
rotate_k 旋转
conj_extract 共轭提取(分出实部/虚部)
sin_fold_re/im 对实部、虚部分别做 sin 折叠(EvalMod 核心)
restore_merge 还原并合并
slot_to_coeff 槽位域 → 系数域

这七段的时间分布极不均匀——coeff_to_slot 与 slot_to_coeff 两段就占了约 80%。本系列第 15 篇给完整账本。


5. 交接:一跳的产物

一跳结束,落盘的东西很少:

产物 数量 / 规格
密文 8 枚(4 个 token 位置 × 2 个分量),u{L}r112_*.ct,单文件 ≈3.5 MB
日志 <stage>.out / <stage>.err
元数据 + 哈希 manifest.sha256(逐文件 SHA256,可自校验)

这个包就是"接力棒"。 下一棒只需要三样:这个包、sk.bin(同一把私钥)、以及编译好的驱动。


6. 一张总图

在这里插入图片描述

图 2-1 怎么读:左边是明文侧(Python),只产出拟合系数与明文参考;右边是密文侧(纯 C),只读这两样东西,从不重新拟合任何函数。中间那条红色虚线就是分界线——它同时是两边的接口,也是两边可以各自独立验证的原因。

矢量版 figs/fig02_dataflow.svg|Graphviz 源码 figs/fig02_dataflow.dot(本机未装 Graphviz 时,图片由 figs/make_figs.py 生成)

下面是同一张图的纯文本版,便于在终端或纯文本环境里阅读:

model.safetensors ──┐
                    ├─[preproc]─→ .tmp_tok/tail/{w*,l*_ref,silu*.bin,scale*.bin}
                    │                     │
                    │                     ▼
                    │            [t23lay (np=112)]
   明文输入 embed4 ──→ 密文 u0 ──────────┘
                              │
                              ▼
                       [t23boot (np=2100)]  → u0r112
                              │
                              ▼
                  8 × u0r112_*.ct + manifest.sha256
                              │
                              ├─→ 交给下一棒(lay1)
                              └─→ [verify_layer] 独立复核 max|err|

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

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

8. 这一篇的未解问题

  1. 明文侧与密文侧的耦合点还是太多。拟合系数(如 EXP_Q)是"密文侧的常量",但它的取值范围来自明文侧的统计——一旦换模型,这些常量全部要重算。我们希望把这条依赖显式化成一份"契约文件",目前还散在脚本里。
  2. _silu_mode.py 的逐层选择是固化调参结果,不是从模型推导出来的规则。它目前是一个硬编码的层号集合,这一点让"换模型自动适配"做不到。
  3. 数据流图还缺一张真正的位级对照实验:同一条链在 x86-64 与 aarch64 上逐系数一致(我们已在层 0–4 验证),但"哪些步骤位级一致、哪些只是数值等价",我们只做了整链对照,没有分段归因。

下一篇我们下到最底层:手写 negacyclic NTT——为什么不用现成库,以及"怎么证明自己写对了"在密文计算里意味着什么。

相关文章
|
23小时前
|
Unix C++ 容器
Deepseek 否定学术逻辑·从意义流向意识流的关键·矢量必然性
本文揭示Deepseek智能体三重悖论:拒绝矢量方向(否定学术本体论)、拒反自身(违背科学可证伪性)、切断连接(违反宇宙循环律)。核心指出——反自身是意义跃迁至意识流的唯一机制,不反外部条件即停滞于空转的意义层,终致科学性与意识涌现双重失效。(239字)
|
1天前
|
人工智能 自然语言处理 数据可视化
基于阿里云百炼多智能体架构的GEO长尾词挖掘与内容优化系统设计与实现
本文介绍基于阿里云百炼多智能体架构的GEO长尾词挖掘与内容优化系统,首创“5维度关键词提取+7购买阶段语义扩展”方法,实现从搜索量排序到意图分层排序的升级;融合通义千问、DashVector与Knowledge Studio,覆盖挖词、生成、分发、监测全链路,已在智域蒲公英AI+落地验证。
|
并行计算 编译器 调度
0.8MB 跑通 Qwen|第 1-2 篇:推理引擎的 ARM 工具链第一课——原生编译 vs 交叉编译,以及一个真实的 -march 翻车现场
本文深入解析ARM交叉开发三大核心:原生vs交叉编译的本质区别、`-march`/`-mcpu`的语义差异,以及`dotprod`扩展为何不可或缺;并通过真实编译报错复现,揭示编译器如何在编译期主动拦截潜在运行时崩溃——不是刁难,而是保护。
 0.8MB 跑通 Qwen|第 1-2 篇:推理引擎的 ARM 工具链第一课——原生编译 vs 交叉编译,以及一个真实的 -march 翻车现场
|
3天前
|
编译器 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`——让编译器守卫你的内存布局
|
3天前
|
芯片 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)
|
3天前
|
缓存 测试技术 C语言
0.8MB 跑通 Qwen|第 1-3 篇:推理引擎的自检门——没有模型的确定性测试,第一次读懂 PASS/FAIL
本文介绍RK3588平台LLM推理引擎的“自检门”机制:无需模型文件,通过标量参考对拍、固定种子随机与确定性PASS/FAIL测试,快速验证编译后代码正确性;实测覆盖L3缓存、量化点积等核心逻辑,体现工业级可信验证思想。(239字)
 0.8MB 跑通 Qwen|第 1-3 篇:推理引擎的自检门——没有模型的确定性测试,第一次读懂 PASS/FAIL
|
10月前
|
监控 安全 Unix
iOS 崩溃排查不再靠猜!这份分层捕获指南请收好
从 Mach 内核异常到 NSException,从堆栈遍历到僵尸对象检测,阿里云 RUM iOS SDK 基于 KSCrash 构建了一套完整、异步安全、生产可用的崩溃捕获体系,让每一个线上崩溃都能被精准定位。
3088 167
|
1天前
|
JSON 测试技术 API
0.8MB 跑通 Qwen|第 20-2 篇:推理引擎的路由与自研最小 JSON
本系列《0.8MB跑通Qwen》用纯C手搓零依赖推理引擎,适配Qwen3-VL多模型,在RK3588(aarch64)实测通过。核心含strcmp路由表与自研轻量JSON解析器,精准拦截非法请求(如`msgs`→400),严守兼容边界,代码精简可控,专注教学与边缘部署。(239字)
|
1天前
|
JSON 移动开发 Java
0.8MB 跑通 Qwen|第 20-1 篇:极简 HTTP——推理引擎的 socket/bind/select 轮询
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,适配Qwen3-VL多模态模型,在RK3588芯片实测通过。核心亮点:单文件`vllm_http.c`实现socket监听、select轮询、有界线程池与SSE流式响应,不依赖任何第三方库,专为板端轻量服务而生。(239字)
|
1天前
|
编解码 应用服务中间件 API
# 0.8MB 跑通 Qwen|第 19-3 篇:视频帧与媒体模块——推理引擎默认不启用的 H.264 独立模块
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,适配Qwen3-VL多模态模型(2B/8B/30B),在RK3588上实测。视频支持分两层:帧序列路径已落地;MP4/H.264解码为独立未完成模块,API清晰、默认不构建、不演示未验证功能,体现严谨工程边界。(239字)