切片执行
说明 assignment 枚举、原生 chunk 并行、确定性归并以及总工作量和驻留内存。
本页目录
单个 slice 的执行过程
执行器先验证输入 shape 和 sliced legs。对一个 assignment,它在原输入张量上选择对应轴值,构造移除 sliced legs 的单片网络,再复用原 SSA path 执行完整收缩。最后一条切片腿在 mixed-radix 编号中变化最快。
0→(0,0)1→(0,1)2→(0,2)3→(1,0)4→(1,1)5→(1,2)chunk 0 · [0,2)T₀ + T₁chunk 1 · [2,4)T₂ + T₃chunk 2 · [4,6)T₄ + T₅partial₀ + partial₁ + partial₂按 chunk index 串行归并use arctn::contract_network_sliced;
let output = contract_network_sliced(
&net, &tensors, &ssa_path, &sliced_legs
)?;
原生执行的 chunk 与归并顺序
单机原生执行把连续 slice index 范围分成若干 chunks。每个 chunk 内按 slice 编号顺序累加;Rayon 可以并行处理不同 chunks;全部完成后,再按 chunk index 串行合并 partial sums。chunk 划分只依赖切片数和输出元素数,不依赖当前线程数。
| 性质 | 实现语义 |
|---|---|
| chunk 数上限 | 最多 256,并受 partial-output 元素预算进一步限制 |
| 线程变化 | 改变 chunks 的完成时机,不改变 chunk 边界和最终合并顺序 |
| 空 sliced legs | 直接进入普通 contract_network |
| 并发驻留 | 每个 in-flight slice 拥有自己的输入副本和中间结果 |
确定性范围
线程数独立的归并顺序用于稳定单机浮点结果;它不意味着 MPI Allreduce 在不同 rank 数下也逐位相同。
总工作量与内存
若切片数为 N, 总 FLOPs 是每片 FLOPs 乘 N。在对数报告中,log10_flops_total = per_slice.log10_flops + log2(N) × log10(2)。切片可能显著降低单片最大结果,同时因重复计算让总 FLOPs 上升。
| 随切片增加通常下降 | 随切片增加通常上升 |
|---|---|
| 单片最大中间结果 | 完整执行的 slice 数 |
| 单个子任务的路径模型内存 | 总 FLOPs 和输入读取 |
| 单片失败时的局部资源需求 | 任务调度、索引和结果累加开销 |
Warning
驻留内存不是 target_size
target_size 只限制单片的二元收缩结果,单张量网络则检查最终输出。原始输入、一元预处理、转置临时量、后端 workspace、partial sums 和同时执行的其他 slices 都会增加实际 RSS。需要总内存上限时,应同时控制并行度并实测进程内存。
三条执行路线
| 路线 | assignment 调度 | 单片收缩 | 结果累加 |
|---|---|---|---|
| Rust / Python native | Rust 按固定 chunks,用 Rayon 并行 | ArcTN Rust CPU executor | chunk 内顺序、chunk 间固定顺序 |
| Python 显式外部 backend | Python 当前按固定顺序串行枚举 | 复用一个 opt_einsum contract_expression | 在所选数组 backend 上相加 |
| tnmpi 主模式 | 各 rank 得到不同连续 slice 区间 | 每个 rank 的 f64 原生执行 | MPI Allreduce |
三条路线共享同一个数学分解,但调度、同步、浮点归并顺序和计时边界不同。跨路线 benchmark 必须明确记录使用的是哪一条执行栈。