【FHE 同态加密】我们如何实现同态加密推理(八):SiLU 的密文化——两条路径,和一个 8 字节的开关(密文非线性激活)

简介: 本文详解SiLU密文化中“一条多项式不够用”的核心矛盾:浅层窄动态需直接拟合,深层宽动态须÷21折叠。8字节开关文件`siluL.bin`决定路径,但缺失时静默启用深层方案,致浅层误差放大百倍——而系统仍显示`RESULT=PASS`。(239字)

【FHE 同态加密】我们如何实现同态加密推理(八):SiLU 的密文化——两条路径,和一个 8 字节的开关(密文非线性激活)

关键词:同态加密 | FHE | SiLU | 非线性激活 | 多项式拟合 | 密文激活 | 折叠 | 大模型推理 | 纯 C11

导读:密文里没有"非线性函数",只有多项式,所以同态加密推理必须把 SiLU 换成多项式逼近——而一条多项式无法同时覆盖浅层窄动态范围与深层宽动态范围。本篇讲两条拟合路径、那个决定路径的 8 字节文件,以及它最危险的一面:文件缺失被静默当成"深层方案",误差放大几十倍,引擎却照样打 PASS。

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

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

0. 一句话结论

密文里没有"非线性函数",只有多项式。所以 SiLU 必须被换成多项式——而一条多项式不可能同时覆盖浅层的窄动态范围和深层的宽动态范围。

我们的做法是逐层选路径,并把选择固化成一个 8 字节的文件:

tail/silu{L}.bin 内容 走的路径 用在哪
1.0 直接拟合(`\ gate\ ≤ 8`,锚定 0) 浅层
0.0 或文件缺失 ÷21 折叠(把动态范围压进逼近窗口) 深层

而这里有一个致命的默认值:文件缺失 = 走折叠路径。于是"文件没生成"这件事,被静默解释成了"请用深层方案"——浅层用错方案,结果是误差放大几十倍,驱动却照样打 PASS。


1. 为什么一条多项式不够用

SiLU 是 x · σ(x)。要把它密文化,就得在某个区间上做多项式逼近。

难点在于动态范围:

  • 浅层的 gate 值域窄(|gate| ≤ 8),而且锚定在 0 附近——此时可以针对这个窄区间做一条精确的拟合;
  • 深层的 gate 值域被前层不断稀释/放大,可能宽到让窄区间拟合完全失效——必须先把输入除以一个常数(这里取 21),把它压进一个固定的逼近窗口,算完再乘回来。

这两种需求是互斥的:为窄区间优化的多项式,放到宽区间上会炸;为宽区间设计的折叠方案,在窄区间上精度差。

1.1 折叠方案的具体缺陷(作者当时写下的理由)

源码注释写得很具体(原文):

silu 模式: silu{lay}.bin=1 → 直接拟合(|gate|<=8, 锚定0, M1c 路径; ÷21 拟合有 ~0.0127
DC 偏移 → 浅层小 gate 相对误差 12-35%); =0/缺省 → ÷21 折叠(M3b 深层)

拆开看这条论证:

  • ÷21 折叠路径的拟合带一个 ~0.0127 的直流(DC)偏移;
  • 在浅层,gate 本身很小,于是这个固定偏移相对于信号而言很大 → 相对误差 12%–35%。

所以在浅层走折叠路径,不是"精度差一点",而是错得离谱。


2. 开关是怎么被读的

完整代码(t23_m3p.c):

/* silu 模式: silu{lay}.bin=1 → 直接拟合(...); =0/缺省 → ÷21 折叠(M3b 深层) */
g_silu_direct = 0;
snprintf(sp, sizeof sp, ".tmp_tok/tail/silu%d.bin", lay);
fp = fopen(sp, "rb");
if (fp) {
   
    double sm = 0;
    if (fread(&sm, 8, 1, fp) == 1 && sm == 1.0) g_silu_direct = 1;
    fclose(fp);
}
if (g_silu_direct) printf("  [silu] lay%d direct\n", lay);

三个必须注意的地方:

  1. 默认值是 0(g_silu_direct = 0),也就是"默认走折叠";
  2. fopen 失败不报错,直接沿用默认值;
  3. 唯一的外部可见信号是那一行 [silu] lay%d direct——只在走直接拟合时才打印。走折叠时什么都不打,和"本来就是深层"长得一模一样。

第 3 点是最阴的:日志里"没有这行"既可能是"这一层本来就该走折叠",也可能是"文件不存在"。


3. 生成端:谁写这些文件

tools/preproc/_silu_mode.py 负责产出全部 26 个文件(silu0.bin … silu25.bin),每个 8 字节 f64。它的核心就是把"哪些层走直接拟合"写成一个集合:

LAY_MAX = 25
# 产出已发布结果的逐层选择:集合内 = 直接拟合(direct),其余 = ÷21 折叠。
DIRECT_LAYERS = {
   0, 1, 2, 5, 6, 8, 10, 11, 12, 13, 14, 15, 16, 18}
for L in layers:
    v = 1.0 if L in DIRECT_LAYERS else 0.0
    with open(os.path.join(a.out, 'silu%d.bin' % L), 'wb') as f:
        f.write(struct.pack('<d', v))

我们核对过:生成的 26 个文件与已分发数据 26/26 逐字节相同,文件名集合完全一致。

3.1 这个集合是"调出来的",不是"算出来的"

按本项目纪律,这点必须明说:DIRECT_LAYERS 是一组固化下来的调参结果,不是从模型推导出的规则。

它意味着两件事:

  • 换模型就要重新调这组数字(不能自动适配);
  • 它是一份"经验资产"而不是"算法"。

我们把这条写在脚本头部注释里,也写在这里,免得后来者以为背后有推导。


4. 事故:一个文件的缺失如何劣化两个数量级

我们重跑 lay0 时漏了 silu0.bin(0 层在 DIRECT_LAYERS 里,本该走直接拟合)。

结果:

指标 数值
驱动输出 RESULT=PASS (0) ✅
独立复核 FAIL 0/8 ❌
实测 `max\ err\ ` 4.2e-2 ~ 8.5e-2
[U2 t3 h0] 单项 4.460e-02

而补上那个 8 字节文件之后,同一层:

[silu] lay0 direct
[A:xnorm t3] max|err|=5.642e-04  PASS
[B:q0    t3] max|err|=1.167e-03  PASS
[C:attn  t0] max|err|=2.858e-04  PASS

误差从 4.5e-2 回到 5.6e-4——差两个数量级。

而这整个过程里,驱动一句抱怨都没有。

(这也是本系列第 14 篇的起点:为什么 RESULT=PASS 不能当判据。)


5. 我们从这件事里改了什么

改动 内容
文档 在数据自检清单里显式列出 tail/silu{L}.bin,并标注"缺了不报错但数值错"
脚本 补上 _silu_mode.py(原来只有驱动读文件、没有生成脚本),并在脚本头写危险警告
口径 把"RESULT=PASS ≠ 数值通过"写进工具文档与复现指南的判据一节
复核 明确要求验收必须跑 verify_layer(独立于驱动的报错逻辑)

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

本文所述参数为机制验证级,远低于 HE 参数标准的 128-bit 水平,不得用于保护真实数据。
本文主张的是:非线性函数密文化时的路径选择与一个真实的失效模式。
本文不主张:安全强度、性能优越性。

7. 这一篇的未解问题

  1. DIRECT_LAYERS 应该被推导出来,而不是枚举。判据其实很明确——"浅层窄值域 → 直接拟合;宽值域 → 折叠",而值域是可以从明文参考统计出来的。这件事在原理上可以自动化,我们还没做。
  2. "缺失即默认"这个模式没有清理。全树里同类的"读不到就用默认值"的文件读取,值得逐一审查。沉默的默认值比崩溃危险得多——崩溃会被发现,默认值不会。
  3. 缺文件时可以自动报错。最直接的止血办法:驱动发现该层在"应有文件"的名单里、而文件不存在时,直接退出。这需要一个"应有清单",目前没有。
  4. 两种路径的误差没有跨层汇总。我们知道单层的差异(0.0127 DC 偏移 → 12–35% 相对误差),但"整条 28 层的链上,路径选择对最终 logits 的影响有多大"没有量化。

下一篇我们看同一类问题的另一面:逐层尺度自适应——为什么"每层用同一个尺度"是行不通的,以及定标时的两个硬约束从哪来。

相关文章
|
18天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
8618 25
|
16天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
3040 14
|
16天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
2110 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
5天前
|
人工智能 JSON Linux
【全网最详细】ComfyUI使用教程:下载+本地部署+配置+工作流搭建一篇搞定(2026最新版)
ComfyUI是一款免费开源的本地AI绘图工具,采用节点式工作流设计,支持文生图、图生图、局部重绘、放大、换脸等多种功能。可离线运行,依赖显卡加速,无需联网。支持自定义流程保存与分享,插件生态丰富,适合进阶用户。(239字)
|
16天前
|
云安全 人工智能 安全
|
11天前
|
人工智能 Linux 开发者
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
Codex是OpenAI推出的AI编程智能体,可读取本地项目、理解需求并自动修改代码。支持桌面GUI、命令行(CLI)及VS Code/Cursor插件三种形态,覆盖可视化操作、终端高效开发与编辑器无缝集成场景,助开发者用自然语言驱动编码全流程。(239字)
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
|
11天前
|
人工智能 JSON 编解码
【2026最新版】ComfyUI本地部署教程,新手也能看懂!
ComfyUI是本地运行的AI绘画工具,采用节点式工作流设计:通过拖拽连接“加载模型”“提示词编码”“采样”“解码”等模块,实现高度可控的文生图。新手推荐使用秋叶整合包,一键启动、内置模型管理与插件安装器,轻松上手。(239字)