batch指令说明

· 预计阅读 7 分钟

batch 是 pSolve 批处理解算的总控制器:它读取控制文件,组织单次实验数据(session)的处理,并根据解算类型调度法方程构建、局部参数消元、全局求解和回代等任务。理解它的重点,是这些任务按什么顺序执行,以及各个子程序如何交接数据和状态。

这里沿着 enter → batch 这条调用链,介绍 BATCH_MAIN 和 BATCH 的主要工作。CTRLS、PRCES 等中间子程序先说明其作用,内部过程留到后面再讨论。

1 batch 指令

batch 以 progs/solve/batch/batch_main.f 为程序入口,将 batch.f 和其他源文件编译得到的目标文件及依赖库链接起来产生。这里的路径相对于 pSolve 源码目录。

通过 psolve 启动批处理解算时,通常先进入 enter,再由它启动 batch。enter 先准备好包含控制文件名、处理进程编号等信息的运行字符串,然后执行:

CALL USE_BUFFER ( NEWBUF, INT2(64), 'OWC' )
CALL RUN_PROG ( 'BATCH', 'PASS', INT2(0) )

这两行代码分别完成数据发送和程序启动。USE_BUFFER 将 NEWBUF 中的 128 字节写入管道;RUN_PROG 随后启动 batch,并通过命令行参数传入运行状态和用户标识。'PASS' 表示把后续执行交出去,正常情况下不再返回 enter 中这个调用点。因此,batch 启动时要接收两部分信息:一部分是命令行中的启动状态,另一部分是管道中的运行字符串。运行字符串包含控制文件的路径,控制文件的具体内容在后面的处理过程中读取。batch 也支持直接接收控制文件等命令行参数,不过据我所知,这种方式几乎没人使用。两种启动方式由 BATCH_MAIN 判断,完成各自的准备后,都调用 BATCH()。这里主要关注由 enter 启动的情况。

batch 整个程序的运行可以分为四个层次:

层次 主要程序 职责
入口 BATCH_MAIN 准备运行环境,接收启动信息,调用总控制子程序,并在正常返回后退出
总控制 BATCH 组织解算准备,调用处理程序,完成解算后的清理
解算准备 CTRLS → CTRLFL 展开、读取控制文件,检查数据,准备新的解算或恢复中断的任务
解算调度 PRCES → ARCSET,以及各解算程序 按处理阶段逐一准备单次实验数据,调用计算程序并保存进度

实际承担法方程构建、求解和回代等计算工作的程序,还包括其他目录中的 PROC_DO、NORML_MAIN、BACK_DO 等。progs/solve/batch/ 目录主要负责围绕这些计算程序组织批处理流程。BATCH_MAIN 和 BATCH 分别定义在 batch_main.f 和 batch.f 中:前者管理程序入口和退出,后者组织批处理任务。

2 BATCH_MAIN

BATCH_MAIN 是 batch 的主程序。它先准备运行环境和启动信息,再调用 BATCH;BATCH 正常返回后,主程序记录完成信息、移除运行占用标记文件并退出。

BATCH_MAIN程序流程图

BATCH_MAIN 的主要操作是:

  • 准备运行环境。 设置进程栈大小和 GOMP_STACKSIZE,再调用 PRE_PROG(),读取启动参数,准备 pSolve 运行所需的公共变量。
  • 处理直接启动的情况。 如果命令行参数数目大于或等于 6,就读取控制文件名等信息,设置是否尝试恢复中断任务、恢复前是否询问,再构造运行字符串,并调用 MAKE_PIPES 建立管道。
  • 处理由 enter 启动的情况。 通过 USE_BUFFER 接收上游传来的运行字符串。是否恢复中断任务等标志也由上游传入,在这个分支中不再重新设置。
  • 执行批处理任务。 两种启动方式完成各自的准备后,都调用 BATCH(),进入批处理的主体部分。
  • 记录完成信息并退出。 BATCH 正常返回后,调用 DBG_END() 记录完成信息,通过 REMOVE_SOLVE_LOCK() 删除运行占用标记文件,最后由 END_PROG() 写入结束记录并退出。这里的运行占用标记文件名为 LOCKxx,其中 xx 是 pSolve 的两字符用户标识。文件中记录程序名、用户、进程号和时间等信息,供程序判断这个用户标识是否正在被使用。REMOVE_SOLVE_LOCK 做的就是删除这份标记文件。

3 BATCH

BATCH 是定义在 batch.f 中的子程序,由 BATCH_MAIN 调用。它按照已经收到的运行信息,读取控制文件、准备工作文件和辅助数据,再调用后续程序执行解算,最后完成清理。

BATCH程序流程图

BATCH 的主要操作是:

  • 做好运行前的设置。 初始化警告信息、待合并矩阵列表和实验数等变量,调用 ERR_MODE 设置出错时的处理方式,再通过 GETENVAR 和 DEBUG_MEM,根据 MEMORY_DEBUG 的设置决定是否启用内存调试。
  • 记录开始信息并计时。 STATUS_SET 记录批处理已经开始,SET_SIGNAL_CTRLC 设置按下 Ctrl+C 等情况下的处理方式,TIM_INIT 开始计时。此外,程序通过 CLRCH、GET_VERSION 和 KBIT 准备并输出版本及恢复模式信息。
  • 读取控制文件,准备解算。 调用 CTRLS,读取运行字符串和控制文件,为解算做好准备。如果本次需要恢复中断的任务,也在这一阶段处理。CTRLS 返回后,BATCH 保存待处理实验数、待合并的 CGM 和输出 CGM 名称等信息,再通过 USE_GLBFIL('OW') 和 USE_GLBFIL_4('WC') 写入 GLBFxx 工作文件,供后面的程序使用。
  • 准备工作文件。 用 INQUIRE 检查旧的约束文件,并调用 UNLINK 删除。用户偏导相关文件(USER_PARTIAL)则通过 BIN_EXIST 检查,根据解算类型和是否恢复任务,决定保留还是重建;相关操作涉及 BIN_UNLINK 以及 OPEN、WRITE、CLOSE,相应分支中的错误由 FERR 处理。
  • 准备 EOP 改正并合并 CGM。 SHFEOP() 准备高频地球定向参数改正,并按配置读取改正文件。如果指定了需要合并的 CGM,就依次调用 ADD_CGM 处理;没有指定时,直接进入下一步。到这里,解算前的准备已经完成。
  • 执行批处理解算。 调用 PRCES,由它按处理阶段逐一处理各次实验数据,并根据解算类型调用相应的计算程序。
  • 完成清理并返回。 PRCES 正常返回后,程序输出此前暂未打印的警告,通过 FC_UNLINK 删除展开后的 .XPND 控制文件,再由 BATCH_CLEANUP() 清理与中断恢复有关的记录。最后,STATUS_SET 标记批处理结束,BATCH 返回 BATCH_MAIN。

解算过程中生成的文本报告称为 spool file,这里称为“解算输出报告”,一般位于 /scr/psolve/spool/SPLFxx,其中 xx 是 pSolve 的用户标识。报告中记录了参数估计结果、各次实验数据的统计信息和部分处理信息,具体内容由输出设置决定。文件大小随实验数量和输出内容而变化,大型解算的报告可能达到数百 MB。可以通过 getpar 从这份报告中提取我们感兴趣的结果,例如射电源位置、测站坐标和地球定向参数等,并分别保存为便于后续分析的文件。