路径指标与优化目标

用 FLOPs、逻辑读写量和内存相关指标比较收缩序,并设置优化目标与切片大小限制。

本页目录

PathStats 的六项指标

PathStats 根据网络结构和收缩序计算工作量与张量大小,不需要数值数组。其中三项累计整条路径的计算与数据访问量,另外三项描述与内存需求相关的张量大小。

字段名中的 log10 和 log2 表示保存的是对数。例如,log10_flops=6 表示 10610^6 次标量乘法,log2_max_size=20 表示最大结果包含 220=1,048,5762^{20}=1{,}048{,}576 个元素。比较同一项指标时,可以直接比较对数值:值越小,对应的工作量或张量大小越小。

设第 ss 个二元步骤的输入和结果为 AsA_s、BsB_s、CsC_s,∣X∣|X| 表示张量元素数,FsF_s 表示该步的标量乘法次数。

字段 定义 回答的问题
log10_flops log⁡10∑sFs\log_{10}\sum_s F_s 整条路径的标量乘法次数
log2_total_size log⁡2∑s∣Cs∣\log_2\sum_s\lvert C_s\rvert 全部结果的写出元素数
log2_read_write log⁡2∑s(∣As∣+∣Bs∣+∣Cs∣)\log_2\sum_s(\lvert A_s\rvert+\lvert B_s\rvert+\lvert C_s\rvert) 整条路径的逻辑读写量

读写量按每步读取两个输入、写出一个结果计数;原始输入按完整数组大小计入。因此,写出量与读写量不是同一项,也都不是硬件实测内存流量。

log2_total_size 将各步结果的大小累计相加。前一步的结果在用完后可以释放,所以这个累计量并不表示这些张量需要同时保存在内存中;同时保留的大小由下面的峰值指标描述。

单步指标计数

本步 FLOPs 按参与二元收缩的 index 维度之积计数;结果大小是保留 index 的维度之积。完整路径指标采用对数表示,避免大型网络的线性计数溢出。

本步结果保留属于 output 的 index,以及仍被这两个输入以外的张量使用的 index;其余参与本步的 index 求和消去。

设 I(X)I(X) 为本步输入张量 XX 的不同 index 集合,did_i 为 index ii 的维度,则

Fs=∏i∈I(As)∪I(Bs)di,∣Cs∣=∏i∈I(Cs)di.F_s=\prod_{i\in I(A_s)\cup I(B_s)}d_i, \qquad |C_s|=\prod_{i\in I(C_s)}d_i.

这个计数包含本步将被求和消去的 index。若执行器先做一元求和,实际运算步骤可能不同;这里统计的是给定二元收缩序的结构代价。复数标量乘法仍计为一次标量乘法,不折算成实数指令数。

三项分别描述最大的结果张量、单步输入与结果的总大小、执行过程中同时保留的张量总大小。都以元素数计量,报告中保存其以 2 为底的对数。

指标 字段 计数范围
最大结果张量 log2_max_size max⁡s∣Cs∣\max_s\lvert C_s\rvert,包括最后的输出
最大单步大小 log2_max_contraction_size max⁡s(∣As′∣+∣Bs′∣+∣Cs∣)\max_s(\lvert A'_s\rvert+\lvert B'_s\rvert+\lvert C_s\rvert)
峰值存活张量大小 log2_peak_size max⁡tLt\max_t L_t,LtL_t 为时刻 tt 尚未释放的张量元素数之和

As′A'_s、Bs′B'_s 是经过一元求和和对角处理后的逻辑输入。峰值统计则计入完整输入;每步先计入新结果,再释放本步输入。

以上一页的三矩阵乘法为例,输入大小为 2×32\times3、3×43\times4、4×54\times5:

指标(元素数,不取对数) (AB)C(AB)C A(BC)A(BC)
最大结果张量 10 15
最大单步大小 38 47
峰值存活张量大小 46 53

两条收缩序的输入总计都是 38 个元素。第一步分别产生 8 或 15 个元素,因此峰值为 38+8=4638+8=46 或 38+15=5338+15=53。对于 (AB)C(AB)C,最终输出的 10 个元素比第一步的 8 个更大,所以最大结果张量为 10。

将元素数乘以每个元素的字节数,可估算相应张量的数据大小。例如 46 个 float64 元素占 46×8=36846\times8=368 字节。这仍不等于进程 RSS 或显存占用:转置临时数组、内存分配器和后端工作区没有计入。

target_size 限制每个 slice 的二元收缩结果元素数;单张量网络另检查最终输出。因此,它限制的是 log2_max_size 所描述的中间张量大小。它不涵盖所有一元临时数组,不直接约束 log2_peak_size,也不等于 RSS 或显存。

如果数值执行同时并行多个 slice,总驻留内存可能明显高于单个 slice 的路径指标。评估内存时还要记录 dtype、线程数、并发 slice 数和实测 RSS。

用指标定义优化目标

路径指标描述计算量和中间张量大小;优化目标决定如何比较不同路径。PlannerObjective 用完整路径的 FLOPs F(P)F(P) 与逻辑读写量 R(P)R(P) 计算目标值:

J(P)=wFF(P)+wRR(P).J(P)=w_F F(P)+w_R R(P).

默认权重为 flops_weight=1、read_write_weight=64。报告中的 planner_objective_score_log2 保存 log⁡2J(P)\log_2 J(P)。

例如,两个候选的 (F,R)(F,R) 分别为 (1000,100)(1000,100) 和 (1200,50)(1200,50)。只比较 FLOPs 时,第一个候选较好;使用默认权重时,二者目标值分别为 7400 和 4400,第二个候选较好,因为它减少了逻辑读写量。各项指标保留这些具体差别,目标值则给出本次搜索采用的排序依据。

权重 目标标签 比较内容
(1, 64) flops_read_write FLOPs 与逻辑读写量的加权和
(1, 0) total_flops 只比较总 FLOPs
(0, 1) total_read_write 只比较总逻辑读写量

权重必须有限、非负,并且不能同时为 0。权重 64 是目标函数中的相对系数,不是字节数、缓存行大小或实测带宽。

在 Python 中指定权重

python
from arctn import arctn_schedule

# 只按 FLOPs 优化;省略这两个权重参数时使用默认值 (1, 64)
report = arctn_schedule(
    inputs, output, size_dict,
    flops_weight=1.0, read_write_weight=0.0,
)

改变权重可能改变候选路径的排名、局部改进的接受结果和最终返回路径。

报告字段 含义
planner_objective 本次调用使用的目标标签;权重分别由 flops_weight 和 read_write_weight 字段报告
planner_objective_score_log2 最终收缩序的加权目标值的 log2;启用切片时计入全部切片
log10_flops / log2_read_write 返回路径在未切片网络上的指标;启用切片后,全部切片的总量分别读取 sliced_log10_flops_total 和 planner_log2_read_write

搜索中的目标函数

权重在寻路入口确定。各生成器可以采用不同的局部启发式,但完整候选、树改进和最终选择使用同一个 PlannerObjective。

局部启发式用于产生候选,不等于完整路径的目标值。例如,随机贪心的一步局部代价用于选择下一对张量,而多次搜索返回的完整路径仍按 J(P)J(P) 比较。

优化目标与切片约束

优化目标用来比较方案的好坏,target_size 则规定单片结果的大小上限。一个方案即使 FLOPs 很低,只要不满足请求的大小限制,就不能作为满足约束的结果返回。搜索中使用的惩罚项不能替代最终的大小检查。

指定切片 index 后,切片数量等于这些 index 维度的乘积。ArcTN 按“单片工作量 × 切片数量”比较切片方案。使用以 2 为底的对数表示时,总目标值的对数等于单片目标值的对数加上 log2_n_slices。

Nslice=∏i∈Sdi,Jsliced=NsliceJone slice.\begin{aligned} N_{\mathrm{slice}}&=\prod_{i\in S}d_i,\\ J_{\mathrm{sliced}}&=N_{\mathrm{slice}}J_{\mathrm{one\ slice}}. \end{aligned}

SS 是切片 index 集合。取对数后:

log⁡2Jsliced=log⁡2Jone slice+log⁡2Nslice.\log_2 J_{\mathrm{sliced}}=\log_2 J_{\mathrm{one\ slice}}+\log_2 N_{\mathrm{slice}}.

该结构模型计入各片的二元收缩,不包含跨片结果求和的额外加法。

log2_peak_size、log2_max_contraction_size 等指标仍会报告,但它们不是上述加权目标的组成项。切片限制的详细说明见切片与 target_size。

计算与比较路径指标

已有网络和 SSA path 时,用 simulate_path 校验路径并计算 PathStats,无需提供数值数组,也不重新搜索:

rust
let stats = arctn::simulate_path(&net, &ssa_path)?;
println!("{:?}", stats);

跨方法或跨库比较时,应在相同网络和维度下,用同一套程序计算路径指标。各库对 FLOPs、读写量以及一元操作的统计方式可能不同;切片后的单片指标也不能直接与全部切片总量比较。测试数据的组成与用途见测试集。

空路径的报告值

单张量网络可以使用空路径,没有二元收缩步骤。此时,Rust 的 log10_flops、log2_total_size 和 log2_read_write 用负无穷表示对应工作量为零,log2_max_contraction_size 为 0;log2_max_size 取最终输出大小,log2_peak_size 仍计入完整输入。

Python 报告同样使用 -inf 表示空路径的零工作量,包括 log10_flops、log2_total_size、log2_read_write 和目标值;请求切片时,sliced_log10_flops_total 也为 -inf。这是零工作量取对数后的表示,不表示搜索或执行失败。