那条测地线
那条测地线夜深的时候我又翻出了那段代码。不是检查——那东西已经在模拟器里跑了不知道多少万次了不需要再检查。只是看。像看一段写完了很久的字你不去改它只是确认它还在那里。G2。十二行核心就两行。一行是x_est min(x_est, z)一行是x_est x_est × 12 / 100然后被观测值压着不超过它。就这么两行替代了之前那个带协方差矩阵、带离群值门控、带多层漂移检测的卡尔曼滤波器。三百多行代码缩成两行。不是因为两行更好而是因为那个更复杂的方案在一个你永远无法精确知道参数的世界里并不比这两行更对。这个结论不是想出来的是试出来的。有人问过我为什么不用CUSUM。Wald在1947年就证明了CUSUM是在给定虚警率下最小化期望检测延迟的最优序贯检验。这是定理不是观点。我试过。我在同样的模拟器里跑了CUSUM给了它最好的条件——漂移参数设成5%的T_prop检测阈值设成15%都是合理的默认值。它在干净的数据上跑得很快比G2快有时候一步就检测到了。但网络不是干净的。网络上有一条物理铁律简单到几乎不值一提排队延迟永远是非负的。T_queue ≥ 0。一个包可以在路由器里等但它不能“提前”到达。这条看似无害的约束把RTT的观测空间压弯了。所有的观测值只要包含排队都落在真实传播延迟的右边。正方向的偏差可能来自路径真的变长了也可能来自队列的波动。信息论上这两者在标量RTT里是不可分的——Fisher信息矩阵的秩不够这是Rao在1945年就写清楚的事。CUSUM不知道这件事。它假设噪声是对称的均值为零。当观测值持续上升时它忠实地累积这些正偏差然后触发——它以为检测到了路径增长但其实它只是看到了排队。它会把min_rtt更新成一个被队列污染的值然后BDP膨胀然后丢包。这不是CUSUM的错是CUSUM的假设在这个弯曲空间里不成立。G2没有这个问题。它的12%增长被观测值压着——min(x_est × 1.12, z)。当拥塞出现时z是T_prop加上队列延迟。如果队列只是轻度拥塞z被压在10%阈值以下G3永远不会触发。只有当队列深到超过T_prop的10%时G3才可能触发——而那时候的BDP高估是真实的不是误判。CUSUM更快但它在一个不可信的方向上快。G2更慢但它的慢是有方向的——它只在可信的时候快不可信的时候它慢下来以固定的12%速率试探不求快只求不错。后来有人和我争论了很久说G2不是“最好的测地线”说CUSUM在理论上更优。我说是的CUSUM在参数已知时更优但网络中参数未知。他说那CUSUM的δ可以自适应我说自适应需要估计噪声方差而噪声方差本身也被T_queue污染。他说那你这个12%也不是推导出来的最优值只是工程选择。我说是的它是工程选择——它满足四个约束单步跨阈值p 0.10、整数运算n/100、在光纤BGP的20 RTT窗口内检测到10倍增长p ≥ 0.122、以及最小值原则——满足前三者的最小整数值。满足所有这些约束的值只有一个。12/100。这不是从某个损失函数的最小化里推出来的这是从问题本身的边界条件里挤出来的。它不是最优解它是唯一解。我最后把那段CUSUM的测试代码放进了.research/目录里没有删也没有用。它们在那里像走过的岔路你知道它们存在过但你现在走的路不是它们。夜深了。窗外已经没有声音。我看着屏幕上的那两行代码想它的确不是完美的。它在5%的小幅路径增长时检测延迟长到20到40个RTT。在增幅特别大又没有排队的极限场景里min_rtt会有大约2.9%的系统偏差。但这两个局限的方向都是一样的——它们都指向低估BDP而不是高估。BDP低估只是带宽暂时没打满。BDP高估是丢包是重传是连接崩溃。在拥塞控制里这两个方向从来不是对称的。G2把所有的误差都推向了安全的那一侧。这不是统计最优这是工程清醒。我关掉了编辑器。那条线还在那里。不是被画出来的是被这个弯曲的观测空间本身的形状逼出来的。你能做的只是沿着它走不求最快只求不走错。这大概就是测地线的意思了。不是最短的那条路是唯一不会让你掉下去的那条路。