mod_phys_lmdz_transfert_para 上层 wrapper 组合
输入范围
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\mod_phys_lmdz_transfert_para.F90
本页范围
本页覆盖 mod_phys_lmdz_transfert_para.F90(1349 行)如何将底层 MPI 和 OMP transfer 模块组合成统一的 bcast/scatter/gather/scatter2D/gather2D/reduce_sum 泛型接口。mpi-data-transfer 和 omp-data-transfer 分别覆盖底层实现;本页聚焦组合层的接口清单、MPI/OMP 执行顺序、临时数组策略和 Mars 物理并行条件。
模块定位
MODULE mod_phys_lmdz_transfert_para
USE mod_phys_lmdz_mpi_transfert
USE mod_phys_lmdz_omp_transfert本模块不包含任何 MPI 或 OMP 原语,只做两件事:
- 分配栈上
Var_tmp临时数组(第一维klon_mpi)。 - 按正确顺序调用底层
*_mpi和*_omp子程序。
所有 MPI/OMP 细节由底层模块处理。
6 个泛型接口总览
| 泛型 | 操作方向 | specific procedures | 支持类型 | 最大维度 |
|---|---|---|---|---|
bcast |
global → all | 22 | c, i/i1-i6, r/r1-r6, l/l1-l6 | 6D |
scatter |
global → local | 12 | i/i1-i3, r/r1-r3, l/l1-l3 | 4D |
gather |
local → global | 12 | i/i1-i3, r/r1-r3, l/l1-l3 | 4D |
scatter2D |
global 2D → local | 12 | i/i1-i3, r/r1-r3, l/l1-l3 | 5D→4D |
gather2D |
local → global 2D | 12 | i/i1-i3, r/r1-r3, l/l1-l3 | 4D→5D |
reduce_sum |
local → sum | 10 | i/i1-i4, r/r1-r4 | 4D |
总计 80 个 specific procedures。计数为 bcast 22 个、scatter/gather/scatter2D/gather2D 各 12 个、reduce_sum 10 个。
维度命名约定
命名后缀含义:_i = scalar integer,_i1 = 2D integer(1D + 额外维),_i2 = 3D,_i3 = 4D。_r 和 _l 类推。_c 仅用于 character scalar。
bcast 特殊地位
- 唯一支持 character 的泛型(仅
bcast_c,因此bcast不是 23 个过程)。 - 唯一支持到 6D 的泛型(
bcast_i6/bcast_r6/bcast_l6),用于高维广播。 - 无临时数组:bcast 直接作用于
Var,MPI 和 OMP 操作同一变量。
执行顺序模式
bcast:MPI 先行
!$OMP MASTER
CALL bcast_mpi(Var)
!$OMP END MASTER
CALL bcast_omp(Var)先由 master 线程执行 MPI rank 间广播,然后所有线程执行 OMP 线程间广播。
scatter:MPI 先行 + 临时数组
TYPE, DIMENSION(klon_mpi, ...) :: Var_tmp
!$OMP MASTER
CALL scatter_mpi(VarIn, Var_tmp)
!$OMP END MASTER
CALL scatter_omp(Var_tmp, VarOut)master 线程执行 MPI rank 间 scatter(全局 → rank 局部),存入 Var_tmp。然后所有线程执行 OMP scatter(rank 局部 → 线程局部)。Var_tmp 第一维为 klon_mpi(当前 rank 的格点数)。
gather:OMP 先行 + 临时数组
TYPE, DIMENSION(klon_mpi, ...) :: Var_tmp
CALL gather_omp(VarIn, Var_tmp)
!$OMP MASTER
CALL gather_mpi(Var_tmp, VarOut)
!$OMP END MASTER与 scatter 相反:先所有线程执行 OMP gather(线程局部 → rank 局部),存入 Var_tmp。然后 master 线程执行 MPI gather(rank 局部 → 全局)。
scatter2D:MPI 2D scatter + OMP 1D scatter
TYPE, DIMENSION(klon_mpi, ...) :: Var_tmp
!$OMP MASTER
CALL scatter2D_mpi(VarIn, Var_tmp) ! 2D 全局 → 1D rank 局部
!$OMP END MASTER
CALL scatter_omp(Var_tmp, VarOut) ! 1D rank 局部 → 线程局部scatter2D_mpi 处理二维空间分解的 scatter(全局 lon-lat → rank 的 band),scatter_omp 处理线程内的列分配。
gather2D:OMP gather + MPI 2D gather
TYPE, DIMENSION(klon_mpi, ...) :: Var_tmp
CALL gather_omp(VarIn, Var_tmp) ! 线程局部 → rank 局部
!$OMP MASTER
CALL gather2D_mpi(Var_tmp, VarOut) ! 1D rank 局部 → 2D 全局
!$OMP END MASTERscatter2D 的逆操作。
reduce_sum:OMP reduce + MPI reduce
TYPE :: Var_tmp ! 标量或数组(无 klon_mpi 维)
CALL reduce_sum_omp(VarIn, Var_tmp) ! OMP 线程间求和
!$OMP MASTER
CALL reduce_sum_mpi(Var_tmp, VarOut) ! MPI rank 间求和
!$OMP END MASTER先 OMP 线程间 reduce,再 MPI rank 间 reduce。Var_tmp 的维度与 VarIn 相同(非 klon_mpi),因为 reduce 的结果不改变空间维度。
临时数组策略
| 操作 | Var_tmp 第一维 | 额外维度 | 来源 |
|---|---|---|---|
| bcast | 无(直接操作 Var) | - | - |
| scatter | klon_mpi |
SIZE(VarOut, 2:...) |
输出侧 |
| gather | klon_mpi |
SIZE(VarIn, 2:...) |
输入侧 |
| scatter2D | klon_mpi |
SIZE(VarOut, 2:...) |
输出侧 |
| gather2D | klon_mpi |
SIZE(VarIn, 2:...) |
输入侧 |
| reduce_sum | SIZE(VarIn, ...) |
同 VarIn | 输入侧 |
关键观察:
- 所有
Var_tmp都是栈上自动数组(非ALLOCATABLE,非SAVE),每次调用自动分配和释放。 - scatter/gather/scatter2D/gather2D 的
Var_tmp第一维始终是klon_mpi(来自mod_phys_lmdz_mpi_data)。 - scatter 的额外维度取自
VarOut(因为 MPI scatter 后的中间结果与线程局部输出维度一致)。 - gather 的额外维度取自
VarIn(因为 OMP gather 后的中间结果与线程局部输入维度一致)。 - reduce_sum 的
Var_tmp没有klon_mpi维度,因为 reduce 不改变空间结构。
类型覆盖差异
| 泛型 | CHARACTER | INTEGER | REAL | LOGICAL |
|---|---|---|---|---|
| bcast | scalar | scalar-6D | scalar-6D | scalar-6D |
| scatter | - | scalar-4D | scalar-4D | scalar-4D |
| gather | - | scalar-4D | scalar-4D | scalar-4D |
| scatter2D | - | scalar-4D | scalar-4D | scalar-4D |
| gather2D | - | scalar-4D | scalar-4D | scalar-4D |
| reduce_sum | - | scalar-4D | scalar-4D | - |
- character 仅 bcast 支持(
bcast_c),其他 5 个泛型无 character 变体。 - reduce_sum 无 LOGICAL 变体(逻辑值求和无物理意义)。
- scatter/gather/scatter2D/gather2D 最高到 4D(
_i3对应输入 4D、输出 4D)。 - bcast 最高到 6D,支持高维 tracer 数组广播。
klon_mpi 依赖
所有使用临时数组的 specific procedure 都在内部 USE mod_phys_lmdz_mpi_data, ONLY : klon_mpi。klon_mpi 是当前 MPI rank 的格点数,由 mod_phys_lmdz_mpi_data 在物理侧初始化时设定。
这意味着:
- 调用任何 scatter/gather/scatter2D/gather2D 前,
mod_phys_lmdz_mpi_data必须已初始化。 Var_tmp的大小在编译时确定(Fortran 自动数组),但klon_mpi的值在运行时确定。- 栈空间需求可能较大:对 4D 数组,
Var_tmp大小为klon_mpi × d2 × d3 × d4 × sizeof(type)。
Mars 物理并行条件经过
Mars 物理并行通过以下路径使用本模块:
getin_p(ioipsl_getin_p_mod.F90):使用bcast泛型广播配置参数。- COMMON 物理公共层:
mod_phys_lmdz_para.F90自检调用scatter2D/bcast/reduce_sum;xios_writefield.F90和misc/wxios.F90使用bcast/gather建立输出网格信息。 - Mars physics 模块:
phymars/conf_phys.F、iostart.F90、surfini_mod.F90、aeronomy 数据读取等直接使用bcast/gather/scatter同步配置、全局场和局部物理列。 - 边界:
calfis_p的动力-物理列搬运是手写 MPI/OMP 路径,不直接调用本模块的scatter/gather泛型。
编译守卫
本模块本身无 #ifdef 编译守卫。它无条件 USE MPI 和 OMP 底层模块。但底层模块内部可能有 CPP_MPI/CPP_PARA 守卫,决定 MPI 调用是真实还是 stub。
顺序对称性总结
| 操作 | 第一步 | 第二步 | 临时数组方向 |
|---|---|---|---|
| bcast | MPI (!$OMP MASTER) |
OMP (all threads) | 无 |
| scatter | MPI (!$OMP MASTER) |
OMP (all threads) | 全局 → rank → thread |
| gather | OMP (all threads) | MPI (!$OMP MASTER) |
thread → rank → 全局 |
| scatter2D | MPI 2D (!$OMP MASTER) |
OMP 1D (all threads) | 2D 全局 → rank → thread |
| gather2D | OMP 1D (all threads) | MPI 2D (!$OMP MASTER) |
thread → rank → 2D 全局 |
| reduce_sum | OMP (all threads) | MPI (!$OMP MASTER) |
thread sum → rank sum → 全局 sum |
scatter/bcast 方向:MPI 先行(global → rank),OMP 后行(rank → thread)。 gather/reduce 方向:OMP 先行(thread → rank),MPI 后行(rank → global)。