系列目录 · 工程与交付 · Read in English
评审会上,有人画出一张漂亮的图:输入张量经过一个算子,输出张量写回内存。再添几行像模像样的汇编,页面顿时显得完整。
接着有人问:“这个配置字段,代码里真有吗?”
房间安静下来。图上的字段只是为了说明逻辑临时取的名字,读者却已经把它当成硬件接口。
技术文档最容易制造的错误,不一定是公式写错,而是不同证据层次看上去一样肯定。
从公式到指令,中间不是一条直线
描述一个算子,至少可以区分五层:
- 数学语义:想计算什么。
- 张量语义:shape、轴、广播、数据类型如何约束。
- 数值表示:scale、零点、舍入、饱和如何定义。
- lowering 与配置:这些信息如何进入目标表示。
- 指令与编码:实际发射什么,字段如何落到位。
前一层成立,不自动证明后一层已经存在。例如知道 Split 可以表达为多个 Slice,不代表目标编译器已经实现这种分解;看见某个指令枚举名,也不代表导入、lowering、内存分配和代码生成已经连通。
所阅读的早期说明反复区分“概念配置”“可能路径”与“已确认字段”。保留这些限定语很重要,它们使文档能够承载设计讨论,而不冒充交付能力清单。
为什么一个小例子要列出那么多条件
假设文档只写:
1 | y = x - b |
读者可能把 b 理解为同形张量、标量或逐通道参数。如果实际示例只覆盖同形输入,却没有说明,后续实现会围绕不同假设展开。
再考虑量化表示 x = s × (q-z)。若输入、输出尺度不同,整数域的减法一般不能简单写成两个整数相减。文档如果只放原始整数示例,恰好又选择相同尺度,就会把最需要解释的重定标问题藏起来。
更好的示例说明至少包含角色、shape、dtype、量化参数、布局,以及哪些值在编译期确定。不是为了表格好看,而是让读者知道这个例子证明了什么,以及没有证明什么。
同名操作为什么仍然不能合并说明
“Max”可能是逐元素取最大值,也可能是沿轴归约,还可能是滑窗池化的一部分;ArgMax 返回的是索引,又多了平局处理和索引位宽。
类似地,推理态 BatchNorm 可以预先折叠固定统计量,使用当前输入动态统计的标准化则不能机械套用同一套常量参数。把两个名字都叫 normalization,不意味着它们有同样的运行数据依赖。
一份可靠文档应主动指出这些容易被名字掩盖的边界。可以使用一张问题表:
| 容易混淆的表达 | 必须补充的问题 |
|---|---|
| max | 比较两个张量,还是归约一条轴 |
| mean | 任意轴归约,还是滑动窗口 |
| power | 普通幂,还是保留符号的幂变换 |
| norm | 统计量来自常量,还是本次输入 |
| reshape | 只改视图,还是需要实际搬运 |
| supported | 有定义、可导入,还是端到端可执行 |
这张表是教学总结,不是任何具体产品的支持列表。
示例地址不应该伪装成资源约束
文档为了画清楚内存布局,常给每个小张量分配一个整齐的地址。问题在于读者可能把这种排版选择理解为真实硬件对齐要求。
更合适的写法是先用符号地址和参数 A 表示对齐,再解释具体例子只是其中一种安排。如果真实对齐仍未确认,应明确保留空白,而不是让一个随手选择的数值变成接口承诺。
同理,示例中一个张量只有几个元素,不代表实现不需要 padding;输入输出都是窄整数,也不代表内部累加器使用同样位宽。把物理字节布局与数学张量描述拆开,后续才能正确讨论容量和地址推进。
文档应该如何帮助发现问题
可以对一个示例做三轮问答。
第一轮只看数学:输入、输出和边界条件是否自洽?例如 reshape 元素数是否相等,卷积输出尺寸能否从属性推导,归约后保留维度的规则是否明确。
第二轮看表示:量化范围是否能够覆盖输出,零点如何参与填充值,索引类型能否覆盖目标轴长度,局部 buffer 是否足够。
第三轮看实现证据:对应转换在哪一层发生?配置来源是什么?测试覆盖了哪些属性组合?若没有完整实现,就停在候选设计,不继续画出肯定的最终机器码。
这些检查可以在写实现之前暴露歧义,也可以在实现之后发现文档落后。它不要求每一页都面面俱到,但要求每一个肯定句拥有相应层次的依据。
“待确认”也需要可以被关闭的条件
无限期保留一个模糊问号,最终只会让文档变成考古现场。每个未知项最好能转成具体问题,例如:
- 这个语义轴在当前布局下对应哪一物理维?
- 量化乘子是编译时生成,还是运行时计算?
- 多输出地址由一个描述符承载,还是拆为多条操作?
- 缺少专用指令时,是否已有经过验证的组合路径?
- 这个测试是只检查 IR,还是已经执行目标程序?
当代码或测试给出答案,就更新对应小节,而不是把整页从“草案”一键改成“支持”。实现成熟度往往按子问题推进,文档也应该能表达这种粒度。
为什么文档本身也值得回归
命令示例里的相对路径错一层,读者就可能在进入算法之前失败。被删除的参数仍留在 README,用户看到的就是一个虚假的入口。把文档随安装产物一起交付以后,链接和必要页面也成了包完整性的一部分。
原历史中既有很小的路径更正,也有大量算子示例与面向使用者的文档整理。它们的技术价值不同,但都应纳入工程叙述:前者修复可复制性,后者梳理语义与实现证据。
建议的验证包括检查示例引用、相对路径、命令选项、公式条件和支持范围。对于只有概念流程的段落,应验证逻辑自洽,而不是假装它是一段可以直接运行的代码。
诚实并不妨碍文章有趣
一个好问题往往比一串肯定句更吸引人:“为什么只改变输出 scale,就让看似相同的减法需要另一套参数?”“为什么一个输入输出同形的操作,仍然可能多出搬运?”这些问题既能引导推理,也不会填补不存在的事实。
真正有价值的技术文档,不是永远显得已经完成,而是让读者知道下一步该验证什么。它把未知变成边界,把边界变成可以讨论和关闭的问题。
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. All the images used in the blog are my original works or AI works, if you want to take it,don't hesitate. Thank you !