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 文件。它包含:
vlsplt_p主例程:传统并行 Van Leer 入口,显式执行vlx_p/vly_p/vlz_p/vly_p/vlx_p,并在 E-W 和垂直段插入 halo 通信。vlx_p:E-W Van Leer 内核,带 band 范围参数、极点行排除、OpenMP 循环和父子 tracer 递归。vly_p:N-S Van Leer 内核,直接使用parallel_lmdz的ij_begin/ij_end,对极点进程条件化处理。vlz_p:垂直 Van Leer 内核,动态分配wq/Ratio,用OMP MASTER/BARRIER保护共享工作数组。minmaxq_p:并行极值诊断,默认只在isminismax编译保护下使用。
当前并行主路径更常见的是 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_end、pole_nord/pole_sud、OMP_CHUNK 等本地 band 和 OpenMP 调度状态。 |
mod_hallo |
Register_Hallo、SendRequest、WaitRecvRequest、WaitSendRequest。 |
infotrac |
nqtot/nqdesc/nqfils/iqfils/qperemin/masseqmin,支撑父子 tracer 比例输送。 |
comgeom.h |
极点面积、经纬度和面积权重。 |
vly_p 把 first/testcpu/temps*、sinlon/coslon/sinlondlon/coslondlon、airej2/airejjm 声明为 THREADPRIVATE。vlz_p 的 first 也是 THREADPRIVATE,但 wq/Ratio 是 ALLOCATABLE,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_p 和 vlz_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 的公式一致,但有三类并行边界:
- 将计算范围限制到
ijb_x:ije_x。 - 若本段包含全局北极或南极行,使用
pole_nord/pole_sud排除极点行。 - 所有主要循环使用
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 缩回,避免越界或重复处理极点。
极点处理与串行版数值意图一致,但并行版按进程条件执行:
pole_nordrank 计算北极qpns、投影和归零。pole_sudrank 计算南极qpsn、投影和归零。- 非极点 rank 不处理极点收支。
极点通量收支也条件化:只有持有极点的 rank 执行 SSUM 和极点行赋值。
vlz_p
vlz_p(q,pente_max,masse,w,ijb_x,ije_x,iq) 是并行版差异最大的方向内核。
wq 和 Ratio 是三维共享数组:
wq(ip1jmp1,llm+1,nqtot)
Ratio(ip1jmp1,llm,nqtot)
首次调用时由 OMP MASTER 分配,并用 OMP BARRIER 保证所有线程可见。垂直边界 dzq(:,1/llm)=0、wq(:,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 一致需用串并行回归验证。
复现检查点
zqhalo 宽度必须是 2,zmhalo 宽度必须是 1;否则边界带附近斜率或质量更新会读错。- 边界带
2*iip1必须和 halo 宽度匹配。 vly_p的扩展范围依赖前一段 halo 已完成;不要把vly_p移到 halo wait 之前。vlz_p的wq/Ratio分配和边界清零依赖OMP MASTER/BARRIER。- 父子 tracer 垂直递归必须保留
w(子)=wq(父)修正。 - 返回前必须等待
MyRequest1/MyRequest2的发送完成。 - 单进程并行运行时要检查
pole_nord和pole_sud同时为真时的条件分支。
相关页面
待确认
- 当前 Mars 并行生产配置的典型 MPI band 数、OMP 线程数和
OMP_CHUNK。 mw/wq/Ratio三维数组在高 tracer 数配置下的缓存和内存压力。- 直接调用
vlsplt_p的旧路径是否仍存在实际构建使用,还是全部由vlspltgen_p替代。