关联 PR:#1142(fully_distributed_within_core runtime)。
背景
在 a2a3sim 上对 fully_distributed_within_core 做大规模验证(paged_attention_unroll,batch≥16,--use-example-exec-time busy-wait 回放路径)时,dist_alloc_tensors 会随机 SIGABRT。本 issue 记录已修复的根因与重构,并提出两点仍需完善的遗留问题。
已修复:alloc 缺少 single-owner 选举导致 heap 回收水位线无符号下溢
现象
- a2a3sim、batch≥16、busy-wait 回放(
--use-example-exec-time)下随机崩溃;OFF(真跑 kernel)与 tmr 同用例均不复现。
- 表象是下游
get_ref 的 always_assert(index < output_count_) 失败 → terminate → SIGABRT。
根因
heap reclaim back-pressure 用了无符号减法 heap_next - vend[F-H] 判断 live window 是否超过 ring。dist_alloc_tensors 此前由每个 core 无条件重放(不像 dist_submit_impl 有 is_winner 选举),因此当某个 core 的重放进度落后全局完成前沿 F 超过 H 个 task 时,会出现 heap_next < vend[F-H],无符号减法回绕到约 2^64 → 误判 "heap ring too small" → set_fatal(),随后 alloc 返回空 TaskOutputTensors{},下游 get_ref 即断言失败崩溃。
只有 busy-wait 回放路径在 batch≥16 触发:真跑 kernel 时各 core 的完成前沿足够接近,没有 core 会落后超过 H。
修复(已在 PR #1142 重构)
给 dist_alloc_tensors 引入与 dist_submit_impl 相同的 single-owner 选举:
- materialize 输出 + producer-map 登记仍每核执行(保持确定性重放一致);
- 之后用一条新的
alloc_cursor 做 claim 选出唯一 owner;
- 只有该 owner 执行 reclaim back-pressure 并发布完成标志。
owner 必然处于/领先于完成前沿(它认领的 task 尚未完成,故 F < N),因此 window 减法不再可能下溢,无需额外的算术保护。把 materialize 提前到(现在仅 owner 执行的)back-pressure 之前,也使真正的 fatal 返回已物化的 result,而非此前会触发断言的空 result。
遗留待解决(可能已在设计文档中作为 feature/limitation 提出)
1. 依赖跨度用常数 H 近似,需要精确依赖 + 配套的内存复用管理
当前用依赖跨度上界 H(kHDefault=64,PTO_DIST_H 覆盖)来界定"某 producer 的最后消费者 id ≤ producer id + H",并据此推导 reclaim 水位线 R = F - H(见 docs/fully_distributed_within_core.md §依赖跨度/回收)。但实际 task 的依赖跨度可以很大且差异显著,常数 H 只是保守近似:
- H 取小 → 可能在真实消费者读取前就回收了 producer 的堆区(运行期 fatal "heap span exceeded");
- H 取大 → live window 占用过多 ring、削弱回收效率。
需要精确的 per-task 依赖区间(而非全局常数),以及与之配套的内存复用/回收管理机制,让回收水位线按真实依赖推进。
2. TensorMap.lookup 的 overlap 判断过于简单,且只返回单个前驱(无法支持 partial update 的多前驱)
dist_engine.cpp 的 MapEntry::lookup:
- overlap 判断仅为简单区间相交
lo < e.hi && e.lo < hi;
- 每个 tensor 只返回 MAX(最新)的一个 overlapping producer(
return best)。
但在 partial update 场景下,一个 INPUT/INOUT 区域可能由多个前驱分别写入其不同子区间,正确的 fan-in 应解析出全部相关 producer,而非只取最新一个,否则依赖图不完整、可能在前驱未完成时就执行消费者。
建议参照 tensormap_and_ringbuffer(tmr)的 overlap 逻辑完善:采用 tmr 的区域重叠判定方式,并让 lookup 支持返回多个 partial 前驱。
相关代码:
src/a2a3/runtime/fully_distributed_within_core/runtime/dist_engine.cpp(MapEntry::lookup、dist_alloc_tensors、reclaim back-pressure)
- 参考:
src/a2a3/runtime/tensormap_and_ringbuffer/runtime/(overlap / 多前驱解析)
关联 PR:#1142(
fully_distributed_within_coreruntime)。背景
在 a2a3sim 上对
fully_distributed_within_core做大规模验证(paged_attention_unroll,batch≥16,--use-example-exec-timebusy-wait 回放路径)时,dist_alloc_tensors会随机 SIGABRT。本 issue 记录已修复的根因与重构,并提出两点仍需完善的遗留问题。已修复:alloc 缺少 single-owner 选举导致 heap 回收水位线无符号下溢
现象
--use-example-exec-time)下随机崩溃;OFF(真跑 kernel)与 tmr 同用例均不复现。get_ref的always_assert(index < output_count_)失败 → terminate → SIGABRT。根因
heap reclaim back-pressure 用了无符号减法
heap_next - vend[F-H]判断 live window 是否超过 ring。dist_alloc_tensors此前由每个 core 无条件重放(不像dist_submit_impl有is_winner选举),因此当某个 core 的重放进度落后全局完成前沿F超过H个 task 时,会出现heap_next < vend[F-H],无符号减法回绕到约2^64→ 误判 "heap ring too small" →set_fatal(),随后 alloc 返回空TaskOutputTensors{},下游get_ref即断言失败崩溃。只有 busy-wait 回放路径在 batch≥16 触发:真跑 kernel 时各 core 的完成前沿足够接近,没有 core 会落后超过
H。修复(已在 PR #1142 重构)
给
dist_alloc_tensors引入与dist_submit_impl相同的 single-owner 选举:alloc_cursor做 claim 选出唯一 owner;owner 必然处于/领先于完成前沿(它认领的 task 尚未完成,故
F < N),因此 window 减法不再可能下溢,无需额外的算术保护。把 materialize 提前到(现在仅 owner 执行的)back-pressure 之前,也使真正的 fatal 返回已物化的 result,而非此前会触发断言的空 result。遗留待解决(可能已在设计文档中作为 feature/limitation 提出)
1. 依赖跨度用常数 H 近似,需要精确依赖 + 配套的内存复用管理
当前用依赖跨度上界
H(kHDefault=64,PTO_DIST_H覆盖)来界定"某 producer 的最后消费者 id ≤ producer id + H",并据此推导 reclaim 水位线R = F - H(见docs/fully_distributed_within_core.md§依赖跨度/回收)。但实际 task 的依赖跨度可以很大且差异显著,常数 H 只是保守近似:需要精确的 per-task 依赖区间(而非全局常数),以及与之配套的内存复用/回收管理机制,让回收水位线按真实依赖推进。
2. TensorMap.lookup 的 overlap 判断过于简单,且只返回单个前驱(无法支持 partial update 的多前驱)
dist_engine.cpp的MapEntry::lookup:lo < e.hi && e.lo < hi;return best)。但在 partial update 场景下,一个 INPUT/INOUT 区域可能由多个前驱分别写入其不同子区间,正确的 fan-in 应解析出全部相关 producer,而非只取最新一个,否则依赖图不完整、可能在前驱未完成时就执行消费者。
建议参照
tensormap_and_ringbuffer(tmr)的 overlap 逻辑完善:采用 tmr 的区域重叠判定方式,并让 lookup 支持返回多个 partial 前驱。相关代码:
src/a2a3/runtime/fully_distributed_within_core/runtime/dist_engine.cpp(MapEntry::lookup、dist_alloc_tensors、reclaim back-pressure)src/a2a3/runtime/tensormap_and_ringbuffer/runtime/(overlap / 多前驱解析)