dyn3dpar/vlsplt_p.F

源码路径:LMDZ.COMMON-6.3\LMDZ.COMMON\libf\dyn3dpar\vlsplt_p.F

Mars 运行参与度:条件经过。vlsplt_p 是并行动力中的 Van Leer split transport 内核;当前 advtrac_p.F90 主要通过 vlspltgen_p 调度 vlx_p/vly_p/vlz_p,旧的直接 vlsplt_p 主例程仍保留并说明完整 halo split 模式。本页用于理解并行 _p 内核本体、halo/OMP/band 边界以及它与串行 vlsplt 的对应关系。

文件角色

vlsplt_p.F 是 1339 行并行 Van Leer split transport 文件。它包含:

当前并行主路径更常见的是 vlspltgen_p:它在一个文件中调度多个 tracer,并直接调用本文件的 _p 内核。因此 vlsplt_p.F 既是旧主入口,也是 vlspltgen_p 的数值内核来源。

子例程清单

子例程 源码行 作用
vlsplt_p 4 旧并行主入口;按 x-y-z-y-x split 调度并插入 halo request。
vlx_p 204 E-W 并行 Van Leer 内核;ijb_x/ije_x 限定计算范围,跳过极点行。
vly_p 591 N-S 并行 Van Leer 内核;THREADPRIVATE 几何缓存,条件处理北/南极。
vlz_p 1040 垂直并行 Van Leer 内核;wq/Ratio 动态分配,父子垂直通量修正。
minmaxq_p 1293 并行极值诊断;使用三维定位数组。

依赖和并行状态

关键 USE 和状态来源:

依赖 用途
parallel_lmdz ij_begin/ij_endpole_nord/pole_sudOMP_CHUNK 等本地 band 和 OpenMP 调度状态。
mod_hallo Register_HalloSendRequestWaitRecvRequestWaitSendRequest
infotrac nqtot/nqdesc/nqfils/iqfils/qperemin/masseqmin,支撑父子 tracer 比例输送。
comgeom.h 极点面积、经纬度和面积权重。

vly_pfirst/testcpu/temps*sinlon/coslon/sinlondlon/coslondlonairej2/airejjm 声明为 THREADPRIVATEvlz_pfirst 也是 THREADPRIVATE,但 wq/RatioALLOCATABLE,SAVE 共享数组,由 OMP MASTER 分配后用 BARRIER 同步。

vlsplt_p 主例程

主例程使用本地 band:

ijb = ij_begin
ije = ij_end
if (pole_nord) ijb = ijb + iip1
if (pole_sud)  ije = ije - iip1

这样 E-W 方向不会在极点行做经向输送。主例程仍按串行同构的 x-y-z-y-x split:

vlx_p -> vly_p -> vlz_p -> vly_p -> vlx_p

区别在于 vlx_pvlz_p 会先计算边界带、注册 halo、发送 request,再计算内区,最后等待接收完成。vly_p 不单独注册 halo,因为前一步的 halo 已使 N-S 邻域在 band 扩展范围内可用。

Halo 重叠模式

第一段 E-W:

vlx_p(..., ij_begin,            ij_begin+2*iip1-1, iq)
vlx_p(..., ij_end-2*iip1+1,     ij_end,            iq)
Register_Hallo(zq, ..., 2,2,2,2, MyRequest1)
Register_Hallo(zm, ..., 1,1,1,1, MyRequest1)
SendRequest(MyRequest1)
vlx_p(..., ij_begin+2*iip1,     ij_end-2*iip1,     iq)
WaitRecvRequest(MyRequest1)

垂直段同样使用 MyRequest2。边界带宽度是 2*iip1,对应两行 halo。zq 注册 2 行 halo,因为 Van Leer 斜率模板需要更宽邻域;zm 注册 1 行,因为质量更新只需相邻质量。

最后一次 vlx_p 直接对 ij_begin:ij_end 全 band 运行,并在子例程返回前执行:

WaitSendRequest(MyRequest1)
WaitSendRequest(MyRequest2)

这保证异步发送缓冲在返回前不再被 MPI 使用。

vlx_p

vlx_p(q,pente_max,masse,u_m,ijb_x,ije_x,iq) 与串行 vlx 的公式一致,但有三类并行边界:

  1. 将计算范围限制到 ijb_x:ije_x
  2. 若本段包含全局北极或南极行,使用 pole_nord/pole_sud 排除极点行。
  3. 所有主要循环使用 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)

父子 tracer 逻辑仍是 masseq/Ratio、递归调用、父更新后恢复子 tracer。递归调用也携带 ijb_x/ije_x,避免子 tracer 访问当前 band 范围之外的 band。

vly_p

vly_p 不接收 band 实参,而是直接用全局并行状态计算扩展范围。典型范围包括:

ij_begin - 2*iip1 : ij_end + iip1
ij_begin - iip1   : ij_end + iip1
ij_begin - 2*iip1 : ij_end + 2*iip1

这些范围用于 N-S 斜率、通量和父子 tracer 比例。若 rank 持有极点,范围会按 pole_nord/pole_sud 缩回,避免越界或重复处理极点。

极点处理与串行版数值意图一致,但并行版按进程条件执行:

极点通量收支也条件化:只有持有极点的 rank 执行 SSUM 和极点行赋值。

vlz_p

vlz_p(q,pente_max,masse,w,ijb_x,ije_x,iq) 是并行版差异最大的方向内核。

wqRatio 是三维共享数组:

wq(ip1jmp1,llm+1,nqtot)
Ratio(ip1jmp1,llm,nqtot)

首次调用时由 OMP MASTER 分配,并用 OMP BARRIER 保证所有线程可见。垂直边界 dzq(:,1/llm)=0wq(:,1/llm+1,iq)=0 也由 OMP MASTER 设置后同步。

父子 tracer 垂直递归有一个重要修正:

w(ij,l,iq2) = wq(ij,l,iq)

源码注释标记为 correction bug le 15mai2015。串行版把父 wq 复制到子 wq;并行版递归入口使用 w 作为通量输入,所以必须把父 tracer 的垂直 tracer 通量写入子 tracer 的 w 槽。递归调用后,散度更新前还有额外 OMP BARRIER,确保所有线程的 wq 已同步。

与串行 vlsplt 的差异

特征 串行 vlsplt 并行 vlsplt_p
计算范围 全域 ij_begin:ij_end band,边界按 pole_* 调整
通信 Register_Hallo + SendRequest + wait
通信重叠 先边界带、后内区
OpenMP OMP DO SCHEDULE(STATIC,OMP_CHUNK)
极点处理 无条件处理两个极点 仅持有极点的 rank 处理
vly 几何缓存 SAVE SAVE + THREADPRIVATE
垂直工作数组 栈上二维 ALLOCATABLE,SAVE 三维 wq/Ratio
子 tracer 垂直通量 wq(child)=wq(parent) w(child)=wq(parent) 修正
诊断 minmaxq minmaxq_p,三维定位更直接

数值公式本身保持同构;差异主要来自分布式内存、halo、OpenMP 和父子 tracer 垂直通量传递实现。是否 bitwise 一致需用串并行回归验证。

复现检查点

  1. zq halo 宽度必须是 2,zm halo 宽度必须是 1;否则边界带附近斜率或质量更新会读错。
  2. 边界带 2*iip1 必须和 halo 宽度匹配。
  3. vly_p 的扩展范围依赖前一段 halo 已完成;不要把 vly_p 移到 halo wait 之前。
  4. vlz_pwq/Ratio 分配和边界清零依赖 OMP MASTER/BARRIER
  5. 父子 tracer 垂直递归必须保留 w(子)=wq(父) 修正。
  6. 返回前必须等待 MyRequest1/MyRequest2 的发送完成。
  7. 单进程并行运行时要检查 pole_nordpole_sud 同时为真时的条件分支。

相关页面

待确认