MPI 执行

读取已有收缩序和切片,在多个 MPI 进程间分配计算并合并结果。

本页目录

按切片分配计算

tnmpi 读取已保存的收缩序和切片集合,将不同切片分给不同 MPI 进程。所有切片使用同一条收缩路径,各进程先累加自己的部分结果,再通过 MPI 的 Allreduce 将各进程的结果逐元素相加,让每个进程都得到完整结果。

收缩序优化与切片选择在执行前完成,可使用 Light、Heavy 或独立算法。各 MPI 进程沿保存的路径执行分配到的切片,在本地完成每片的矩阵计算,并保存完整输入张量和完整输出。

保存收缩序与切片

用 arctn_plan 生成收缩序文件:

python
from arctn import arctn_plan

plan = arctn_plan(
    inputs, output, size_dict,
    preset="heavy", target_size=1048576,
)
plan.save("plan.json")

文件保存网络结构、SSA 路径和切片 index,不保存数组数值。MPI 执行使用其中的最终路径和切片,不受生成时采用 fixed 或 dynamic 模式的影响。切片集合为空时,只有一个完整网络任务。

也可以用 tnpath 的 --save-path 保存独立算法的结果。第 2 版文件包含网络,无需再传 --net;第 1 版文件需要额外提供对应的网络 JSON。

构建与运行

安装系统 MPI 后构建执行程序,见安装说明。

bash
cargo build --release --locked --features mpi --bin tnmpi

mpirun -n 4 target/release/tnmpi \
  --load-path plan.json --data tensors.bin

--dtype 选择输入和收缩计算的数据类型,默认 f64:

--dtype 每个元素的表示 每个元素的字节数
f32 32 位实数 4
f64 64 位实数 8
complex64 实部和虚部各为一个 f32 8
complex128 实部和虚部各为一个 f64 16

tensors.bin 按输入张量顺序连续存放数组,各数组使用行优先、小端格式,不含文件头。复数的每个元素先存实部,再存虚部;所有输入必须使用与 --dtype 一致的数据类型。complex128 表示总共 128 位的复数,不是 128 位实数。例如:

bash
mpirun -n 4 target/release/tnmpi \
  --load-path plan.json --data tensors-complex128.bin --dtype complex128

各进程必须能访问相同数据。未指定 --data 时,会按 --seed 生成所选类型的相同演示数组;这个 seed 不参与收缩序优化。最终 Allreduce 使用与所选类型对应的 MPI 数据类型逐元素求和。

执行后,编号为 0 的 MPI 进程(rank 0)输出 JSON 摘要,包括进程数、切片数、单片路径指标和时间:

复用同一份收缩序文件和输入,就能比较不同进程数下的执行。若切片数小于进程数,多出的进程没有切片可算,但仍参与结果合并。

结果核对

bash
mpirun -n 2 target/release/tnmpi \
  --load-path plan.json --data tensors.bin --check

--check 在 rank 0 用单进程切片收缩核对结果。输出超过 2222^{22} 个元素或切片超过 2122^{12} 个时跳过对照,并在摘要中标明。浮点求和顺序可能随进程数和 MPI 实现变化,因此不同运行的结果不保证逐位相同。

target_size 限制每片产生的单个中间张量元素数,不是进程 RSS 上限。输入、最终输出和执行临时空间仍需各进程容纳,增加进程数不会使这些内存自动按比例缩小。

线程与作业设置

每个 MPI 进程的切片循环顺序执行。Rayon 默认每进程 1 个线程,可通过 RAYON_NUM_THREADS 设置。启用 mt feature 后,可通过 MATMUL_NUM_THREADS 设置进程内矩阵乘法的线程数。

CPU 绑定和作业时间上限由 MPI 启动器或作业调度器管理。