mod_phys_lmdz_transfert_para.F90

源码基线:LMDZ.COMMON-6.3\LMDZ.COMMON。 Mars 运行参与度:条件经过。Mars physics 和 COMMON 物理公共层通过本模块的 bcastgatherscatter 等泛型完成物理列数据在 MPI ranks 和 OpenMP threads 之间的组合传输。

源码范围

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\mod_phys_lmdz_transfert_para.F90

该文件 1349 行,只定义 MODULE mod_phys_lmdz_transfert_para。模块本身不声明 PRIVATEPUBLIC,因此其中 6 个 generic interface 和 80 个具体 SUBROUTINE 按 Fortran 默认规则公开。

模块职责

mod_phys_lmdz_transfert_para 是物理侧 transfer 的组合层。它不直接调用 MPI API,也不直接使用 OpenMP runtime API;真正的通信和线程内复制在底层两个模块中完成:

依赖 源码行 用途
mod_phys_lmdz_mpi_transfert 6 提供 bcast_mpiscatter_mpigather_mpiscatter2D_mpigather2D_mpireduce_sum_mpi
mod_phys_lmdz_omp_transfert 7 提供 bcast_ompscatter_ompgather_ompreduce_sum_omp
mod_phys_lmdz_mpi_data:klon_mpi 各 scatter/gather 过程内部 决定 rank 局部物理列数,用作 Var_tmp 第一维。

组合层负责三件事:

  1. 通过泛型接口隐藏标量/数组 rank 和类型差异。
  2. 对 scatter/gather 类操作建立 rank 局部临时数组 Var_tmp
  3. 固定 MPI 与 OMP 两层操作的执行顺序,保证全局、rank 局部和 thread 局部数组形状一致。

泛型接口清单

泛型 行号 specific procedures 支持类型和维度 方向
bcast 11-16 22 character scalar;integer/real/logical scalar 到 6D root/global -> all ranks/threads
scatter 18-22 12 integer/real/logical scalar 到 4D global 1D physical columns -> thread local columns
gather 25-29 12 integer/real/logical scalar 到 4D thread local columns -> global 1D physical columns
scatter2D 31-35 12 integer/real/logical scalar 到 4D output;input 多一个 lon-lat 维 global 2D lon-lat field -> thread local columns
gather2D 37-41 12 integer/real/logical scalar 到 4D input;output 多一个 lon-lat 维 thread local columns -> global 2D lon-lat field
reduce_sum 43-46 10 integer/real scalar 到 4D thread/rank partial values -> global sum

计数依据:bcastbcast_c 加上 integer、real、logical 各 7 个过程,共 22 个;另外四个 scatter/gather 泛型各 12 个;reduce_sum 为 integer 和 real 各 5 个。全文件共 80 个 SUBROUTINE

过程分组

行段 过程族 核心模式
57-320 bcast_c, bcast_i*, bcast_r*, bcast_l* master thread 先调用 bcast_mpi(Var),然后所有线程调用 bcast_omp(Var);无临时数组。
327-532 scatter_i*, scatter_r*, scatter_l* master thread 调 scatter_mpi(VarIn, Var_tmp),所有线程调 scatter_omp(Var_tmp, VarOut)
542-747 gather_i*, gather_r*, gather_l* 所有线程先调 gather_omp(VarIn, Var_tmp),master thread 再调 gather_mpi(Var_tmp, VarOut)
757-963 scatter2D_i*, scatter2D_r*, scatter2D_l* master thread 调 scatter2D_mpi(VarIn, Var_tmp),所有线程调 scatter_omp(Var_tmp, VarOut)
972-1177 gather2D_i*, gather2D_r*, gather2D_l* 所有线程调 gather_omp(VarIn, Var_tmp),master thread 再调 gather2D_mpi(Var_tmp, VarOut)
1186-1345 reduce_sum_i*, reduce_sum_r* 所有线程先调 reduce_sum_omp(VarIn, Var_tmp),master thread 再调 reduce_sum_mpi(Var_tmp, VarOut)

执行顺序

bcast

!$OMP MASTER
  CALL bcast_mpi(Var)
!$OMP END MASTER
CALL bcast_omp(Var)

bcast 是唯一支持 character 的泛型,也是唯一扩展到 5D/6D 的泛型。它没有 Var_tmp,MPI 和 OMP 层都直接作用于同一个 Var

scatterscatter2D

TYPE, DIMENSION(klon_mpi, ...) :: Var_tmp
!$OMP MASTER
  CALL scatter_mpi(VarIn, Var_tmp)       ! 或 scatter2D_mpi
!$OMP END MASTER
CALL scatter_omp(Var_tmp, VarOut)

scatter 方向是 global -> rank -> thread,因此 MPI 层先执行。scatter2D 只改变 MPI 步骤:它把全局 lon-lat 二维形状散到 rank 局部 1D physical-column 形状,再交给同一个 scatter_omp

gathergather2D

TYPE, DIMENSION(klon_mpi, ...) :: Var_tmp
CALL gather_omp(VarIn, Var_tmp)
!$OMP MASTER
  CALL gather_mpi(Var_tmp, VarOut)       ! 或 gather2D_mpi
!$OMP END MASTER

gather 方向是 thread -> rank -> global,因此 OMP 层先执行。gather2D 的最后一步调用 gather2D_mpi,把 rank 局部 1D physical-column 形状还原到全局 lon-lat 二维输出。

reduce_sum

TYPE :: Var_tmp
CALL reduce_sum_omp(VarIn, Var_tmp)
!$OMP MASTER
  CALL reduce_sum_mpi(Var_tmp, VarOut)
!$OMP END MASTER

reduce_sum 先在线程内求和,再在 MPI ranks 间求和。它的 Var_tmpVarIn 同形,不带 klon_mpi 第一维,因为 reduce 不表示物理列分布变换。

临时数组形状

所有 Var_tmp 都是过程内自动数组,不是 ALLOCATABLESAVE 或模块状态。数组在调用进入时按实参维度和 klon_mpi 建立,调用返回时释放。

操作 Var_tmp 第一维 额外维度来源 例子
bcast bcast_r6 直接传 Var(:,:,:,:,:,:)
scatter klon_mpi SIZE(VarOut, 2:...) scatter_r3 建立 REAL(klon_mpi, SIZE(VarOut,2), SIZE(VarOut,3), SIZE(VarOut,4))
gather klon_mpi SIZE(VarIn, 2:...) gather_l2 建立 LOGICAL(klon_mpi, SIZE(VarIn,2), SIZE(VarIn,3))
scatter2D klon_mpi SIZE(VarOut, 2:...) scatter2D_i1VarIn(:,:,:)VarOut(:,:)
gather2D klon_mpi SIZE(VarIn, 2:...) gather2D_r3VarIn(:,:,:,:)VarOut(:,:,:,:,:)
reduce_sum klon_mpi SIZE(VarIn, ...) reduce_sum_i4 建立与 4D VarIn 同形的 integer Var_tmp

复现时要先确认物理并行初始化已经给出正确的 klon_mpi。若 klon_mpi 与实参的物理列维不一致,错误通常会在底层 transfer 或数组越界检查中暴露,而不是在本 wrapper 层显式检查。

调用方和运行链

COMMON 内部直接使用本模块的路径包括:

调用方 用到的泛型 用途
phy_common/mod_phys_lmdz_para.F90 scatter2D, bcast, reduce_sum test_phys_lmdz_para 自检物理侧分布和 transfer。
phy_common/ioipsl_getin_p_mod.F90 bcast master 读配置后广播到其它 ranks/threads。
phy_common/xios_writefield.F90 bcast 临时 XIOS field dump 建 regular 输出网格时同步 ni_glo/nj_glo
misc/wxios.F90 gather, bcast XIOS domain 参数构造时聚合/同步全局经纬度数组。

Mars 源码侧也直接使用本模块,常见模式是:

需要区分:dynphy_lonlat/calfis_p.F 的动力格点到物理列搬运有手写 MPI/OMP 循环和 wind exchange,不是本模块泛型的直接调用方。

副作用和状态

本模块不保存模块级变量,也不分配持久内存。它的副作用来自底层调用:

复现要点

  1. 先完成 init_physics_distribution -> init_phys_lmdz_para -> init_phys_lmdz_mpi_data/Init_phys_lmdz_omp_data,使 klon_mpiklon_omp 和线程切片有效。
  2. 判断方向:global 到 local 用 scatterscatter2D,local 到 global 用 gathergather2D,全体同步用 bcast,求和用 reduce_sum
  3. 判断全局输出是否是 lon-lat 2D 空间:若是,用 scatter2D/gather2D;若是 physical-column 1D 全局向量,用 scatter/gather
  4. 检查 rank/类型支持:bcast 到 6D,scatter/gather 到 4D,reduce_sum 无 logical 和 character。
  5. 不要从 wrapper 层寻找通信 buffer、barrier 或 MPI datatype 细节;这些在 MPI/OMP 底层模块页展开。

待确认

相关页面