编译与复用

对固定网络和收缩序准备一次执行所需的信息,再用于多组数值数组。

本页目录

编译一次,重复执行

当网络结构、维度和收缩序不变,只有数组值发生变化时,可以先编译一次,再对多组数组执行。这样既不重新寻路,也不必每次重新准备同一收缩表达式。

寻路决定“先收缩哪两个张量”;编译进一步确定“每一步怎样排列轴、怎样组织矩阵乘法”;执行才将这些步骤应用到实际数组上。复用编译对象省去了重复的准备工作,每组新数组仍需完成相应的数值计算。

这里的编译是准备执行所需的收缩步骤,不是为每组输入重新生成机器代码。编译对象不保存输入数值。

原生后端准备哪些信息

Rust 的 CompiledContraction 保存一元处理所需的轴、每步输入的轴排列、批量矩阵乘法的形状,以及最终输出的轴顺序。后续 execute 直接使用这些信息。

每次执行仍会检查输入数量、形状和 DenseTensor 布局。

pseudocode
steps = 根据网络和收缩序准备轴排列、矩阵形状与输出顺序
对每组输入数组 arrays:
    检查数组与网络是否匹配
    result = 按 steps 执行数值收缩

Python 复用对象

假设已取得 ssa_path,arrays0 和 arrays1 是两组数值不同的输入数组。两组数组都按 inputs 的顺序排列,并保持各个数组的形状和轴含义一致:

python
from arctn import ArcTNCompiledContraction

compiled = ArcTNCompiledContraction.compile(
    inputs, output, size_dict,
    ssa_path=ssa_path,
    backend="numpy",
)
y0 = compiled.execute(arrays0)
y1 = compiled.execute(arrays1)
print(compiled.stats())

y0、y1 分别是两组数组的收缩结果;第二次 execute 继续使用同一个 compiled。例如,在固定量子线路结构中更新门参数,只要门张量的连接关系和维度不变,就可以按这种方式复用。

backend compile 保存的对象 execute
native Rust CompiledContraction 调用 Rust CPU 执行器
已安装的 opt_einsum 数组后端,如 numpy、cupy、torch、jax 固定的 opt_einsum contract_expression 使用指定后端执行表达式

默认使用 backend="native";可显式选择其他后端,不接受 "auto"。外部后端及其依赖需要单独安装。

ssa_path= 必须是 SSA 格式,不是 opt_einsum 的 linear path。SSA 使用固定的张量编号;linear path 使用当前张量列表中的位置,收缩后这些位置会改变。

复用条件

ArcTNCompiledContraction 用于当前进程;改变网络结构、维度或 SSA path 后,需要重新编译。

需要保存到文件的是网络、收缩序和切片信息,而不是编译对象。可使用 ArcTNExecutionPlan 保存和加载;无切片时再调用一次 plan.compile(),复用其返回对象。对于无切片收缩,直接重复调用 plan.execute() 也不会重新寻路,但每次都会重新创建编译对象。

Python 的编译接口不支持非空的切片集合。执行已保存的切片集合时,使用 ArcTNExecutionPlan.execute(),或通过 to_tree() 交给 Cotengra。

Rust 还提供 execute_stripped:每步矩阵乘法后,若最大幅值为正且有限,则按该幅值归一化,并单独累计以 10 为底的缩放指数。这用于避免数值尺度过大或过小,不做截断或近似。