经年治世

西风烈,长空雁叫霜晨月

一个函数名,装不下它的数值契约:非线性与归一化的边界

定义域、近似、精度与归约轴,比函数名字更重要。

系列目录 · 工程与交付 · Read in English “函数名字没写错,输入形状也对,为什么结果差这么多?” 同事把错误样本缩成两个负数。原先看起来只是一点误差的问题,忽然变成了正负号相反。排查到最后,双方实现的竟然不是同一个函数。 非线性运算经常以一个短名字出现在图里:Pow、Sigmoid、Softmax、Norm。真正决定答案的,却是这个名字背后的定义域、公式、轴、常数、近似方......

相同的输出形状,完全不同的答案:池化、缩放与索引归约

窗口分母、插值坐标和最大值索引决定具体答案。

系列目录 · 工程与交付 · Read in English “形状、类型、内存大小都对,怎么还差一个像素?” 排查人盯着放大后的特征图,发现每隔几列就有一条细小的差异。另一边,池化测试只有边缘不一致。大家把它们当成两个独立问题,后来才意识到,它们问的是同一句话:输出坐标到底怎样对应输入? 形状描述了有多少个答案,却没有定义每个答案如何计算。窗口边界、采样位置、舍入规则和索引选择,才决定了形......

它只是在搬数据,为什么还会算错:张量变换的隐藏契约

坐标、步长、别名和量化参数,让搬数据也有语义。

系列目录 · 工程与交付 · Read in English “这个补丁应该很安全,它没有计算,只是移动一下数据。” 半小时后,下游矩阵乘法的结果全变了。大家先检查乘法,再检查量化比例,最后发现搬运操作保持了每个字节,却改变了每个字节代表的位置。 数据移动最容易获得一种不应有的信任:只要数值没变,语义就没变。张量的语义还包括坐标、形状、布局、别名关系和量化轴。搬对了字节,不一定搬对了张量。 ......

一条指令的四种身份:代码生成为什么不能只靠字符串

数学运算、内核、发射与编码的四层职责和错误归属。

系列目录 · 工程与交付 · Read in English “只是发一条乘法指令,为什么要经过四层?” 评审桌上有人写下一行 emit("mul", a, b, out)。它短小、直接,甚至很像最终汇编。另一位同事问:“这个 a 是张量、寄存器编号、内存地址,还是要被广播的标量?” 房间安静了几秒。字符串的简洁,来自它把问题藏起来了。 编译器代码生成中的一条指令,往往经......

搜索到了算子名字,就可以写进“支持列表”吗?

从存在一个名字到完整编译路径,支持需要多层证据。

系列目录 · 工程与交付 · Read in English 用户发来一张模型图:“这个节点你们不是支持吗?我在源码里搜到了。” 开发者也搜了一遍,果然有定义、有推理函数,甚至有测试文件。但模型还是停在后端。两边都没有说谎,只是“支持”这个词装进了不同含义。 一条算子路径上有多少道门 把模型编译想成一次接力,会更容易理解: 12模型导入 → 语义表示 → 目标 lowering → 优化与......

一份算子文档最有价值的词,可能是“尚未确认”

规范要保留未知项,避免把示例表格写成能力承诺。

系列目录 · 工程与交付 · Read in English 评审会上,有人画出一张漂亮的图:输入张量经过一个算子,输出张量写回内存。再添几行像模像样的汇编,页面顿时显得完整。 接着有人问:“这个配置字段,代码里真有吗?” 房间安静下来。图上的字段只是为了说明逻辑临时取的名字,读者却已经把它当成硬件接口。 技术文档最容易制造的错误,不一定是公式写错,而是不同证据层次看上去一样肯定。 从公式......

汇编看起来对了,机器码也会对吗?

伪汇编、汇编、机器码与数学参考各自证明什么。

系列目录 · 工程与交付 · Read in English “生成的汇编跟预期一样,所以代码生成器没问题。” 如果二进制编码器和汇编打印器是两条不同路径,这个结论少了一半。打印器可能正确显示某个枚举名字,而编码器把对应字段写错位置。反过来,机器码可能正确,只是调试汇编误导了排障者。 测试代码生成器,必须先问清楚自己正在观察哪一个对象。 三个输出层,各自会撒什么谎 一个典型发射器可能提供可......

同一份发布包,为什么每次哈希都不同?

区分归档事件时间、包内时间和字节可复现性。

系列目录 · 工程与交付 · Read in English “源码没动,安装目录没动,为什么今天打出来的压缩包和昨天不是同一个哈希?” 最初的直觉通常是怀疑某个文件内容变化。展开归档逐个比较,却发现内容相同。真正变化的可能是文件顺序、时间戳、拥有者,或者压缩层写入的额外时间信息。 发布包不仅包含程序,也包含许多关于“它是怎样被装进去的”的元数据。 先分清两个不同的“相同” 语义相同,是指......

编译已经失败,目录里为什么还有一个“成功的模型”?

输出目录、临时产物和旧文件,让成功与失败可判断。

系列目录 · 工程与交付 · Read in English 早上一次编译成功,下午改了模型再编译失败。自动化脚本检查输出文件仍然存在,于是把上午的模型送去运行。最后大家围着下午的新图讨论错误输出,调查对象却从一开始就拿错了。 这个场景说明了一个关于产物契约的反例:文件存在,不等于本次操作成功地产生了它。 输出参数首先是一个语义承诺 命令行里的 --output 看起来只是字符串,实际决定......

把一堆编译产物装成一个文件,到底难在哪里?

模型文件作为协议,必须定义偏移、长度与所有权。

系列目录 · 工程与交付 · Read in English “既然最终只想要一个文件,把整个目录压缩一下不就行了?” 这句话对备份很合理,对运行时加载却未必成立。运行时可能需要直接知道输入输出张量、指令段位置、参数段长度和目标地址。它不想猜目录约定,也不能把编译器临时文件全部当成正式接口。 因此,模型文件首先是生产者与消费者之间的协议,然后才是一串字节。 文件偏移和设备地址,不住在同一个......