parallel physics grid distribution

输入范围:physics_distribution_mod.F90mod_grid_phy_lmdz.F90mod_phys_lmdz_para.F90,并确认 mod_phys_lmdz_mpi_data.F90mod_phys_lmdz_omp_data.F90inigeomphy_mod.F90、Mars iniphysiq_mod.F90dimphy.F90 调用边界。 Mars 运行参与度:条件经过。Mars 3D 物理初始化从 iniphysiq_mod -> inigeomphy -> init_physics_distribution 进入本链;Mars 1D/testphys 路径也直接调用 init_physics_distribution(regular_lonlat,4,1,1,1,...) 来建立单列物理维度。

源码范围

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\physics_distribution_mod.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\mod_grid_phy_lmdz.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\mod_phys_lmdz_para.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\mod_phys_lmdz_mpi_data.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\mod_phys_lmdz_omp_data.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dynphy_lonlat\inigeomphy_mod.F90
LMDZ.MARS\libf\dynphy_lonlat\phymars\iniphysiq_mod.F90
LMDZ.MARS\libf\phymars\dimphy.F90

职责

本页说明物理列分布初始化的完整约定:上游把动力经纬网格规模、当前 MPI rank 的物理列数和 communicator 传入 COMMON;COMMON 先写全局物理网格状态,再生成 MPI rank 与 OpenMP thread 的列切片,最后把每个 OpenMP 线程看到的 klon/klev 写入 Mars physics 的 dimphy

这条链不是字段传输本身。实际 scatter/gather/bcast/reduce 在 MPI data/transferOMP data/transferphys-transfer-para-wrapper 中实现;本页只解释这些传输例程依赖的分布表和局部维度如何建立。

入口和参数

physics_distribution_mod:init_physics_distribution 定义在 physics_distribution_mod.F90:9-31

参数 方向 维度/类型 含义
grid_type in integer 物理网格类型;Mars lon-lat 路径传 regular_lonlat
nvertex in integer cell 顶点数;regular lon-lat 路径传 4
nbp in integer 当前 MPI rank 的物理列数。
nbp_lon in integer 全局 regular 网格经向点数。
nbp_lat in integer 全局 regular 网格纬向点数;Mars 3D 从 inigeomphyjjm+1
nbp_lev in integer 物理垂直层数。
communicator in integer 物理侧 MPI communicator,写入 COMM_LMDZ_PHY

Mars 3D 入口在 iniphysiq_mod.F90:57-64 调用 inigeomphy。COMMON inigeomphy_mod.F90:82-87 再按两种形态调用本入口:

3D: init_physics_distribution(regular_lonlat, 4, nbp, iim, jjm+1, nlayer, communicator)
1D: init_physics_distribution(regular_lonlat, 4, 1,   1,   1,     nlayer, communicator)

Mars phymars/dyn1d/init_testphys1d_mod.F90 也直接调用同一入口,并在有/无 MPI communicator 的两种分支下传 COMM_LMDZ1

总体调用链

Mars iniphysiq
  -> COMMON inigeomphy
       -> init_physics_distribution
            -> init_grid_phy_lmdz
            -> init_phys_lmdz_para
                 -> init_phys_lmdz_mpi_data
                 -> OMP parallel:
                      -> init_phys_lmdz_omp_data
                      -> klon_loc = klon_omp
                      -> is_master = is_mpi_root .and. is_omp_root
                      -> Test_transfert
            -> OMP parallel:
                 -> init_dimphy(klon_omp, nbp_lev)
       -> init_interface_dyn_phys
       -> build global physical geometry arrays
       -> OMP parallel:
            local slice = klon_mpi_begin + klon_omp_begin/end
            -> init_geometry(klon_omp, ...)
       -> init_vertical_layers(...)
  -> Mars OMP parallel:
       phys_state_var_init(klon_omp, ...)
       ini_fillgeom(klon_omp, ...)
       conf_phys(klon_omp, ...)

init_grid_phy_lmdz 必须先于 init_phys_lmdz_para,因为 Test_transfert 会使用 mod_grid_phy_lmdz:klon_glo/nbp_lev 构造全局测试数组。

全局网格状态

mod_grid_phy_lmdzinit_grid_phy_lmdzmod_grid_phy_lmdz.F90:39-59 保存:

状态 含义
grid_type regular_lonlatunstructured
nvertex 每个 cell 顶点数。
nbp_lon, nbp_lat, nbp_lev 全局经向、纬向、垂直层规模。
klon_glo 全局物理列数,去掉两极重复经度。

klon_glo 的源码公式为:

if nbp_lon * nbp_lat == 1:
    klon_glo = 1
else:
    klon_glo = nbp_lon * nbp_lat - 2 * (nbp_lon - 1)

mod_phys_lmdz_mpi_data.F90:68-74 用等价形式重算局部变量:

1D: klon_glo = 1
3D: klon_glo = nbp_lon * (nbp_lat - 2) + 2

两者在 3D regular lon-lat 情况下相同:每个极点从 nbp_lon 个重复经度压缩为一个物理列。

MPI rank 级分布

mod_phys_lmdz_para:Init_phys_lmdz_paramod_phys_lmdz_para.F90:19-41 先调用 Init_phys_lmdz_mpi_data(nbp,nbp_lon,nbp_lat,communicator)

mod_phys_lmdz_mpi_data.F90:47-182 做以下事情:

  1. 根据 CPP_MPI 设置 is_using_mpi;无 MPI 时令 mpi_size=1mpi_rank=0
  2. MPI 构建下用 MPI_COMM_SIZE/RANK 读取 COMM_LMDZ_PHY 的 size/rank。
  3. MPI_ALLGATHER(nbp,...) 收集每个 rank 的物理列数;无 MPI 时 distrib(:)=nbp
  4. klon_mpi_para_nb(:)=distrib(:)
  5. 由前缀和构造 klon_mpi_para_begin/end
  6. 把 1D 物理列区间映射回二维 regular lon-lat 线性区间 ij_para_begin/end
    • rank 0 从 ij=1 开始,保留北极物理列。
    • 其他 rank 用 klon_mpi_para_begin(i)+nbp_lon-1 把去重后的物理列重新嵌入带极点重复经度的 2D 线性网格。
  7. 推导 ii_para_begin/endjj_para_begin/endij_para_nbjj_para_nb
  8. 当前 rank 写入 ii_begin/endjj_begin/endij_begin/endklon_mpi_begin/endklon_mpi

极点所有权由 rank 位置决定:

标志 条件 含义
is_north_pole_dyn mpi_rank == 0 北极物理列在第一个 rank。
is_south_pole_dyn mpi_rank == mpi_size-1 南极物理列在最后一个 rank。
is_mpi_root mpi_rank == 0 MPI root,和 OMP root 合成 is_master

这套表供 transfer、XIOS、debug 写场、calfis_p 周边逻辑和 geometry 切片使用。nbp 必须已经由上游动力/物理接口按当前 rank 算好,本模块不重新决定负载平衡。

OpenMP thread 级分布

Init_phys_lmdz_para 随后进入 OpenMP parallel 区,在每个线程调用 Init_phys_lmdz_omp_data(klon_mpi)

mod_phys_lmdz_omp_data.F90:25-106 的分配规则是平均切分当前 rank 的 klon_mpi

for thread i = 0 .. omp_size-1:
    klon_omp_para_nb(i) = klon_mpi / omp_size
    if i < mod(klon_mpi, omp_size):
        klon_omp_para_nb(i) += 1

klon_omp_para_begin(0) = 1
klon_omp_para_end(0)   = klon_omp_para_nb(0)
for i = 1 .. omp_size-1:
    begin(i) = end(i-1) + 1
    end(i)   = begin(i) + nb(i) - 1

每个线程写入自己的 threadprivate 状态:

状态 来源 含义
omp_rank, omp_size OpenMP runtime 或串行 fallback 当前线程编号和线程总数。
klon_omp klon_omp_para_nb(omp_rank) 当前线程物理列数。
klon_omp_begin/end klon_omp_para_begin/end(omp_rank) 当前线程在 rank 内的列区间。
is_omp_root omp_rank == 0 当前 rank 的 OMP root 线程。
is_north_pole_phy is_north_pole_dyn .and. omp_rank == 0 北极列由第一个 rank 的第一个线程拥有。
is_south_pole_phy is_south_pole_dyn .and. omp_rank == omp_size-1 南极列由最后一个 rank 的最后一个线程拥有。

mod_phys_lmdz_para 在同一 parallel 区内设置 klon_loc=klon_omp,并把 is_master 设为 is_mpi_root .AND. is_omp_root

dimphy 局部维度

physics_distribution_mod.F90:28-30 再开一个 OpenMP parallel 区,按线程调用 Mars dimphy:Init_dimphy(klon_omp, nbp_lev)

Mars dimphy.F90:1-29 中:

状态 线程属性 初始化
klon THREADPRIVATE 每个线程写自己的 klon0,即 klon_omp
klev, klevp1, klevm1 THREADPRIVATE OMP MASTER 赋值后 BARRIER;parallel 区内线程获得一致垂直层状态。

因此 Mars physics 中大量 USE dimphy, ONLY: klon/klev 的例程看到的是当前 OpenMP 子域维度,而不是全局 klon_glo 或 rank 级 klon_mpi

几何局部切片

inigeomphy_mod.F90 在初始化分布后构造全局物理几何数组,再进入 OpenMP parallel 区把全局列切给每个线程。关键索引在 inigeomphy_mod.F90:224-234

offset = klon_mpi_begin - 1
local global slice = offset + klon_omp_begin : offset + klon_omp_end

airefi(:)      = airefi_glo(local slice)
airefi_outputs = aire_glo(local slice)
cufi/cvfi      = cufi_glo/cvfi_glo(local slice)
lonfi/latfi    = lonfi_glo/latfi_glo(local slice)
bounds         = bounds_glo(local slice, :)
ind_cell_glo_fi = local global indices

随后 inigeomphy_mod.F90:237-241 调用 init_geometry(klon_omp,...)init_geometry_cell_area_for_outputs(klon_omp,...)F90:244-248 调用 init_vertical_layers。这说明分布初始化不仅决定 transfer 维度,也决定 Mars physics 看到的经纬度、面积、边界和垂直层状态。

复现顺序

复现 Mars 3D 物理初始化时,最小顺序如下:

1. 上游动力/并行层决定每个 rank 的 nbp 和 communicator。
2. iniphysiq 调用 inigeomphy(ii,jj,nlayer,nbp,communicator,...)
3. inigeomphy 调用 init_physics_distribution:
   a. init_grid_phy_lmdz 写全局网格和 klon_glo
   b. init_phys_lmdz_mpi_data 收集 nbp,建立 rank 级 klon_mpi 表
   c. init_phys_lmdz_omp_data 切分 klon_mpi,建立 thread 级 klon_omp 表
   d. Init_dimphy 写 Mars physics 的 klon/klev
4. inigeomphy 根据 klon_mpi_begin + klon_omp_begin/end 截取几何数组。
5. Mars iniphysiq 在 OMP parallel COPYIN 后调用 phys_state_var_init、ini_fillgeom、conf_phys,均使用 klon_omp。

常见误读

输出与副作用

模块 写入状态
mod_grid_phy_lmdz grid_type/nvertex/nbp_lon/nbp_lat/nbp_lev/klon_glo
mod_phys_lmdz_mpi_data MPI rank、size、root、pole 标志、rank 级二维/一维分布表、COMM_LMDZ_PHY
mod_phys_lmdz_omp_data OMP rank、size、thread 级列分布和 pole 标志。
mod_phys_lmdz_para klon_loc/is_master/is_sequential/is_parallel
dimphy Mars physics 当前线程的 klon/klev/klevp1/klevm1
geometry_modregular_lonlat_modvertical_layers_mod 后续由 inigeomphy 用分布结果写入局部几何、regular grid 和垂直层。

本链没有外部文件 I/O。Init_phys_lmdz_mpi_dataInit_phys_lmdz_omp_dataTest_transfert 会向 lunout 打印分布和 checksum 诊断。

待确认

相关页面