定位 inner_ms 的 3.3 倍:是争抢不是算法档,撤回 22/86 拆分
服务端跑 probe_inner.py 与本机对表:分档占比一致(TF_DF 两腿 68~74%, 信号链 16~21ms),此前报的「chan 构建 22ms / 信号链 86ms」是无效减法 ——孤立环境的 1m append 减在场十币的 inner_ms,还漏了 5m 腿。 真实构成:inner_ms 100ms = 约 30ms 计算 × 3.3 倍争抢。逐个排除 _rebuild(1.6ms)、币种差异、周期重建(21.5%/1.5x)、批内次序(相关-0.083) 后,用外生的到达密集度确认(67→117ms),并以注入合成负载复现 (2 个满载进程 2.68x,3 个 2.86x,在场实测 2.24~3.34x)。 心跳判定不再推荐「继续压算法」,改为加核或减币。 第一版用 t_signal-inner_ms 反推并发区间得相关 0.533,是循环构造, 已废弃并在 §5.72 记下这个坑。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+71
-3
@@ -1581,9 +1581,14 @@ python step46_engine_parity.py --check --rows 200000 --out step46_baseline_big.j
|
|||||||
**十币 / 2 核的效果:** 清空 560→247ms,排队 92→10ms,纯计算 219→108ms,
|
**十币 / 2 核的效果:** 清空 560→247ms,排队 92→10ms,纯计算 219→108ms,
|
||||||
内存 597→598MiB(20 条缓存流的开销在噪声里)。
|
内存 597→598MiB(20 条缓存流的开销在噪声里)。
|
||||||
|
|
||||||
**瓶颈已经换位置了:** `inner_ms` 108ms 里 chan 构建只占约 22ms,其余 86ms
|
~~**瓶颈已经换位置了:** `inner_ms` 108ms 里 chan 构建只占约 22ms,其余 86ms
|
||||||
是 `build_htf_zones` / `find_fast_bsp3` / `attach_htf_context`。再压 chan
|
是 `build_htf_zones` / `find_fast_bsp3` / `attach_htf_context`。~~
|
||||||
构建收益有限,要继续压得看下游那三个。
|
|
||||||
|
⚠️ **上面这段是错的,2026-08-28 撤回,见 §5.72。** 那个 86ms 不是测出来的,
|
||||||
|
是减出来的:22ms 是孤立环境下 1m 腿的 `append_bar`,108ms 是跑着的十币采集器
|
||||||
|
里的 `inner_ms`。一个无争抢一个有争抢,还漏了 5m 腿,这个减法不成立。
|
||||||
|
实测信号链合计只有 16~21ms,`build_htf_zones` 是其中最大的一项(13ms),
|
||||||
|
`find_fast_bsp3` / attach 合计不到 2%。
|
||||||
|
|
||||||
#### 5.71 第二轮引擎优化(2026-08-28,服务端反馈驱动)
|
#### 5.71 第二轮引擎优化(2026-08-28,服务端反馈驱动)
|
||||||
|
|
||||||
@@ -1635,6 +1640,69 @@ EMA/MACD/ATR 是递推的、BB/SMA/量比是窗口的,理论上都能 O(1) 更
|
|||||||
**曾怀疑是 payload 反序列化,实测 `_rebuild` 只有 1.0ms,假设不成立。**
|
**曾怀疑是 payload 反序列化,实测 `_rebuild` 只有 1.0ms,假设不成立。**
|
||||||
两边跑同一个探针对分档表,才能定位那 86ms。
|
两边跑同一个探针对分档表,才能定位那 86ms。
|
||||||
|
|
||||||
|
**→ 已定位,见 §5.72:那 86ms 不存在,是服务端的减法错了。分档两边一致。**
|
||||||
|
|
||||||
|
#### 5.72 那 86ms 不存在:`inner_ms` 的 3.3 倍是争抢,不是某个算法档
|
||||||
|
|
||||||
|
服务端跑了同一个 `probe_inner.py`(2 核,采集器十币在跑)。**分档占比两边
|
||||||
|
对得上,四倍差距是伪命题:**
|
||||||
|
|
||||||
|
| | 本机 | 服务端 |
|
||||||
|
|---|---|---|
|
||||||
|
| `TF_DF` 两条腿 | 70% | **68~74%** |
|
||||||
|
| `build_htf_zones` | 13% | 10~12% |
|
||||||
|
| `htf_fx_timeline` | 6% | 5% |
|
||||||
|
| `find_fast_bsp3`+ladder+attach | <2% | **<2%** |
|
||||||
|
| 信号链合计 | — | **16~21ms**(不是 86ms) |
|
||||||
|
|
||||||
|
服务端那个 22/86 是无效减法(见 §5.7 的撤回批注)。
|
||||||
|
|
||||||
|
**但对完表冒出一个真问题:** 探针里全量 `TF_DF` 合计 106~126ms,而采集器走
|
||||||
|
增量报的 `inner_ms` 也是 100ms 中位——增量该快得多,两个数却一样。差额去哪了?
|
||||||
|
排查顺序与结论:
|
||||||
|
|
||||||
|
| 假设 | 实测 | 判定 |
|
||||||
|
|---|---|---|
|
||||||
|
| `_rebuild` 反序列化贵 | 两腿合计 **1.6ms** | ✗ |
|
||||||
|
| 某些币结构复杂 | 十币中位 92~105ms,几乎一致 | ✗ |
|
||||||
|
| 周期性全量重建拉高中位 | 占 21.5%,且只贵 1.5x(133 vs 91ms) | 部分 |
|
||||||
|
| 批内后段被拖慢 | `inner_ms` 对批内次序相关 **−0.083**,是平的 | ✗ |
|
||||||
|
| **CPU 争抢** | 见下 | **✓ 主因** |
|
||||||
|
|
||||||
|
「批内平坦」一度被我读成争抢的反证,其实反了:**两个 worker 在整段突发期都
|
||||||
|
满载时,批内每个币被拖慢的程度一样,平坦正是均匀争抢的表现。**
|
||||||
|
|
||||||
|
用外生指标(到达密集度,仅由 `t_data_ms` 决定,不含 `inner_ms`):
|
||||||
|
|
||||||
|
| ±250ms 内到达币数 | 1 | 2 | 4 | 6 | 8 |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| `inner_ms` 中位 | 67ms | 80ms | 94ms | 105ms | 117ms |
|
||||||
|
|
||||||
|
⚠️ **第一版用 `beg = t_signal_ms − inner_ms` 反推并发区间,得到相关 0.533,
|
||||||
|
这个数是废的**——`inner_ms` 越大区间越宽、重叠自然越多,相关性有一部分是构造
|
||||||
|
出来的。换外生指标后相关降到 0.271。**凡是用被解释变量去构造解释变量的,先
|
||||||
|
怀疑循环。**
|
||||||
|
|
||||||
|
注入合成负载复现(离线同一窗口,2 核):
|
||||||
|
|
||||||
|
| 背景 | `compute` 增量 | 放大 |
|
||||||
|
|---|---|---|
|
||||||
|
| 空闲 | **29.9ms** | 1.00x |
|
||||||
|
| 1 个满载进程 | 41.7ms | 1.39x |
|
||||||
|
| 2 个满载进程 | 80.2ms | 2.68x |
|
||||||
|
| 3 个满载进程 | 85.4ms | 2.86x |
|
||||||
|
|
||||||
|
采集器实测:密集度=1 时 67ms(2.24x)、总体中位 100ms(3.34x)。落在「1~2 个
|
||||||
|
满载进程」到「2 个以上」之间,正是 **2 核上跑 主进程 + 2 worker** 该有的样子
|
||||||
|
(主进程常驻负载不小:10 路 K 线 WS + 10 路盘口 + 10Hz 采样)。
|
||||||
|
|
||||||
|
**结论与代价:** `inner_ms` 100ms = **约 30ms 真实计算 × 3.3 倍争抢**。
|
||||||
|
剩下的延迟不是算法性质的,继续压引擎收益有限(把 30ms 砍一半只换回 15ms×3.3
|
||||||
|
≈ 50ms,且越往下越难)。真正的杠杆是**核数**或**减币**。
|
||||||
|
|
||||||
|
⚠️ 这和 §5.7 心跳里「币数 > 核数时加 worker 无用」不矛盾但要分清:**加 worker
|
||||||
|
确实无用(worker 已等于核数),加核有用。** 两者在原判定里被混成一句了。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. 接下来要做的事(按优先级)
|
## 6. 接下来要做的事(按优先级)
|
||||||
|
|||||||
@@ -856,7 +856,9 @@ class Shadow:
|
|||||||
144ms 抬到 192ms,反而超过 queue 135ms,于是判定落到「量级已低、
|
144ms 抬到 192ms,反而超过 queue 135ms,于是判定落到「量级已低、
|
||||||
无需优化」,而此时最后一个币已经落在 1376ms。
|
无需优化」,而此时最后一个币已经落在 1376ms。
|
||||||
|
|
||||||
所以币数超过核数时,唯一的出路是压单币耗时(增量计算),不是加 worker。
|
所以币数超过核数时,加 worker 不增吞吐。出路有两级:先上增量把真实计算
|
||||||
|
压下来;增量之后剩的是争抢放大(实测 3.3 倍,§5.72),那一级只能加核或
|
||||||
|
减币,继续改算法收益有限。
|
||||||
"""
|
"""
|
||||||
if not np.isfinite(clear):
|
if not np.isfinite(clear):
|
||||||
return "样本不足,暂不判定"
|
return "样本不足,暂不判定"
|
||||||
@@ -872,10 +874,13 @@ class Shadow:
|
|||||||
if not INCR_ON:
|
if not INCR_ON:
|
||||||
return (f"币数 {len(SYMS)} > 核数 {CORES},加 worker 无用(CPU 密集)"
|
return (f"币数 {len(SYMS)} > 核数 {CORES},加 worker 无用(CPU 密集)"
|
||||||
f"。压单币耗时 → 开 SHADOW_INCR=1 走增量(实测 3.56x)")
|
f"。压单币耗时 → 开 SHADOW_INCR=1 走增量(实测 3.56x)")
|
||||||
return (f"币数 {len(SYMS)} > 核数 {CORES},且增量已生效。单币 {i:.0f}ms "
|
# 增量已生效时,单币耗时的大头不再是算法而是争抢:离线同一窗口 30ms,
|
||||||
f"里 chan 构建仅约 22ms,其余是 build_htf_zones / "
|
# 在场 100ms,注入合成负载能复现这个倍数(HANDOFF §5.72)。所以这里不能
|
||||||
f"find_fast_bsp3 / attach_htf_context —— 要继续压得改这三个,"
|
# 再推荐「继续改算法」——那是按 3.3 倍虚高的数去优化 30ms 的真实计算
|
||||||
f"或减币")
|
return (f"币数 {len(SYMS)} > 核数 {CORES},增量已生效,加 worker 无用"
|
||||||
|
f"(worker 已等于核数)。单币 {i:.0f}ms 里真实计算约 30ms,"
|
||||||
|
f"其余是 {CORES} 核上争抢的放大 —— 杠杆是加核或减币,"
|
||||||
|
f"不是继续压算法")
|
||||||
|
|
||||||
async def run(self) -> None:
|
async def run(self) -> None:
|
||||||
await self.start()
|
await self.start()
|
||||||
|
|||||||
Reference in New Issue
Block a user