预算
Ants 允许每次适配器求值 1,000,000 次运算。每个已声明输入的适配器各有自己的一百万,所以有两个输入的清单就有两份:上限按每次求值计,而一次调用会对每个输入的适配器求值。这个计数不含推理,而整个调用(你的适配器加上计算图)必须在回合时限内完成。
什么算一次运算
- 求值器访问的每一个表达式节点计 1:一个操作符、一个字面量、程序中写出的数组的每个元素。循环体对它遍历的每个元素都再付一次,求值器跳过的分支不付费。
- 被常量折叠的子树不计费,求值器识别出同一子树出现了两次时也只计一次。两者都是优化,也都可能随版本变化。
- 每个张量操作符还要为它搬运的元素计费,各自的规则见下文。节点在执行之前计费,所以会超出预算的操作符会被拒绝,根本不会运行。
- 集合和字符串操作符按项计费:
merge、in、keys、values、entries、sort、distinct、group_by、cat、split和深度相等比较,每项计一次,字符串则每 64 字节计一次。所以在reduce里用merge构建的累加器,每一步都要为它复制的每一项付费,开销按平方增长。
{"zeros": [[128, 128], "i8"]} 的开销约为 16,389:操作符本身 1,它生成的元素 16,384,再加上对参数求值的几次(形状数组、其中的两个数字,以及数据类型)。
各操作符的计费
每个操作符在自身的 1 和对参数求值的开销之外,再收取下面的费用。n 是张量参数的元素数,m 是结果的元素数。
| 操作符 | 计费 |
|---|---|
zeros, full | m |
tensor | m |
scatter | 点数和 m 中的较大者。一次 scatter 要为整个网格付费,无论它写入的点多么少 |
rle_expand | len(runs) 和 m 中的较大者 |
one_hot | len(indices) × depth |
stack, concat | 所有输入的元素总数 |
unstack, transpose, cast, normalize, to_list | n |
pad, crop, gather | n 和 m 中的较大者 |
argmax | n:它要读取全部元素 |
reshape, shape, dtype | 1:重塑不搬运任何元素 |
平台不保证这些数字。引擎自己的文档写明,运算次数可能随版本变化:新的快速路径或常量折叠会改变引擎实际分派的内容。按实际工作量做预算,在你测得的数字之上留出余量。上限 1,000,000 而用到 990,000 的适配器,离一次判罚只差一个补丁版本。
真实清单的开销
基线的适配器构建七个平面,逐段解读一份真实清单完整讲解了它。2026 年 10 月 1 日,tinybrains adapt 在参考观测上测量了它,覆盖该参考集所取自的五张基础地图。最小、中等和最大地图上的最差情况:
| 地图 | 格数 | 操作数 | 占预算 |
|---|---|---|---|
| 24 × 24 | 576 | 8,131 | 1% |
| 48 × 64 | 3,072 | 43,113 | 4% |
| 120 × 124 | 14,880 | 208,427 | 21% |
开销随地图的格数变化:每格约 14 次运算,因为七个平面每个都是完整的网格,而 stack 又把七个全读了一遍。蚂蚁、敌人、食物和蚁丘各加几次运算,在取整里就被忽略了。赛季的地图可以从 24 × 24(576 格)到 14,880 格不等,最大的那张花掉预算的五分之一。
超出预算意味着什么
计费一越过预算,节点就立刻停止求值。在审核时这是拒绝,原因为 ADAPTER_OVER_BUDGET;在对局中这是一次判罚,和错过时限一样,累计五次判罚该席位就判负。节点从不重试:同一个适配器在同一份观测上,在任何机器上的开销都相同。
通过审核并不能证明之后的每个回合都在预算内。节点是在真实输入上计数的,残局的回合(更多蚂蚁,视野内更多食物和敌人)可能比任何参考用例都贵。开销随地图变化的适配器(基线的就是这样)保持可预测;循环遍历蚂蚁或可见物体的适配器,开销会随对局推进而增长。
提交前测量
tinybrains adapt model.onnx manifest.json 打印每个参考用例的计费,--obs 则测量你自己的观测。tinybrains check 报告最差情况及其占预算的比例。提交前的测试两者都有讲。
节省开销
- 用
scatter和rle_expand构建平面,绝不要用 JSON 循环逐格构建。 - 每个平面每格约两次运算:构建它一次,stack 读取它一次。去掉计算图用不到的平面,是成本最低的节省办法。
- 读取
vis:它只需一次rle_expand,而且这门语言无法表达它的推导过程(为什么)。 - 尽量用一个输入而不是多个。每个输入都是一次独立的求值,有自己的一百万,也都要重新读一遍观测。
- 策略头不花你任何开销,因为是裁判来读它。如果你自己写程序把它读回来,就要为每一格的全部五个通道付费:在 128 × 128 上约 82,000 次运算。
在限制的整个范围内测试:120 × 124 的地图格数约是 24 × 24 的 26 倍,开销随地图变化的适配器在它上面的开销也就是那么多倍。