切片计算与求和
枚举切片取值、并行执行并汇总结果,以及切片对总计算量和内存的影响。
本页目录
计算每个切片,再把结果相加
确定路径和切片 index 后,才开始实际的数组计算。每组 index 取值对应一个子任务:从输入张量中取出相应的数据,再按方案中的收缩路径得到该片结果。所有切片计算完后,将结果逐元素相加,得到原网络的收缩结果。
例如,一个维度为 2 的内部 index 被切片后,计算两个结果 、,最终结果为 。这就是“按切片方案执行收缩”,不是再次搜索路径。
0→(0,0)1→(0,1)2→(0,2)3→(1,0)4→(1,1)5→(1,2)分组 0 · [0,2)T₀ + T₁分组 1 · [2,4)T₂ + T₃分组 2 · [4,6)T₄ + T₅partial₀ + partial₁ + partial₂按分组编号依次合并部分和use arctn::contract_network_sliced;
let output = contract_network_sliced(
&net, &tensors, &ssa_path, &sliced_legs
)?;
并行计算与结果求和
原生执行器把连续编号的切片分成若干组(chunk)。每组按切片编号顺序累加,Rayon 并行处理不同组;完成后再按组编号依次合并部分和。分组只依赖切片数和输出元素数,不依赖线程数。
| 项目 | 具体行为 |
|---|---|
| 分组数上限 | 最多 256,并受部分输出的元素数预算限制 |
| 线程变化 | 改变各组的完成时机,不改变分组和最终合并顺序 |
| 无切片 index | 直接调用 contract_network |
| 并发内存 | 同时执行的每个切片都有自己的输入副本和中间结果 |
线程数独立的归并顺序用于稳定单机浮点结果;它不意味着 MPI Allreduce 在不同 rank 数下也逐位相同。
总工作量与内存
若切片数为 ,全部切片的二元收缩工作量为
切片可能降低单片最大结果,同时因重复计算使总 FLOPs 上升;模型计数不含最终跨片求和的额外加法。
| 随切片增加通常下降 | 随切片增加通常上升 |
|---|---|
| 单片最大中间结果 | 完整执行的切片数 |
| 单个子任务的路径模型内存 | 总 FLOPs 和输入读取 |
target_size 只限制单片的二元收缩结果,单张量网络则检查最终输出。原始输入、一元预处理、转置临时量、后端工作区、部分和以及同时执行的其他切片都会增加实际 RSS。控制总内存时,还需考虑执行并行度。
三条执行路线
| 路线 | 切片任务调度 | 单片收缩 | 结果累加 |
|---|---|---|---|
| Rust / Python native | Rust 按固定分组,用 Rayon 并行 | ArcTN Rust CPU 执行器 | 组内、组间均按编号顺序累加 |
| Python 外部后端 | Python 按固定顺序串行枚举 | 复用一个 opt_einsum.contract_expression |
在所选数组后端上相加 |
| tnmpi | 各进程执行不同的连续切片区间 | ArcTN Rust CPU 执行器;--dtype 支持四种实数 / 复数类型,见 MPI 执行 |
MPI Allreduce |
三条路线使用相同的数学分解,但任务调度、同步和浮点归并顺序不同。性能测试应注明执行路线。