田块尺度的作物–土壤模型,写成纯 JAX 函数:依据已发表的方程独立实现,并对照 DSSAT-CSM(BSD-3 协议)与 RZWQM2 的输出进行验证。右侧的图随阅读变化:先是一个矩阵,行为生长季,列为天;随后是实测结果。
上述倍率比较的是两个工作量不同的程序:DSSAT-CSM 写出完整的逐日文件并运行整个作物–土壤模型,Agri-JAX 只运行已验证的逐日模型并返回十条逐日序列。在 192 核整节点上,首次运行比 DSSAT-CSM 慢(0.85×);各行结果见第三幕。
向下滚动,图随阅读变化;也可以用图下方的按钮逐帧播放。悬停、聚焦或点击带下划线的数字,可查看其条件。
十万个生长季:DSSAT-CSM 一个接一个地跑,Agri-JAX 一天一天地一起走
- 1.1DSSAT-CSM 在一个核上把 10⁵ 个生长季一个接一个地跑完:实测 1426 s,写出 30.3 GB 的逐日文本。屏幕上为加速播放。
- 1.2在同一个核上,Agri-JAX 每一步让所有生长季前进一天。首次运行(含编译)用时 99.1 s,热启动 56.0 s,重复调用 48.9 s;十条逐日序列留在内存中(1.5 GB),不写任何文件。相对 DSSAT-CSM,这里分别快 14× · 25× · 29×(首次运行 · 热启动 · 重复调用)。
- 1.3为什么可以换走法:每个格子只依赖同一行中它左边的格子,即一个生长季的今天只依赖它自己的昨天。
- 1.4行与行之间没有箭头:一个生长季的水分从不进入另一个生长季的方程。
- 1.5于是两层循环可以对调:外层循环遍历天,内层对每一行施加同一个操作。一列就是对十万个数的一条指令,这正是向量单元与 GPU 所擅长的形状。
- 1.6一列就是 DSSAT 的一天:土壤反照率与水桶模型的水量速率、潜在蒸散发、土面蒸发与蒸腾、根系吸水、水桶模型的状态更新、CERES-Maize 的生长,以及水量账。这一天的各个模块均由模型自行模拟;只有尚未移植的模块所产生的内容(残留物记录、逐日土壤性质变化)取自 DSSAT 回放。
同一个矩阵、同一比例尺,只是遍历顺序不同。两边所做的工作并不相同:DSSAT-CSM 运行整个作物–土壤模型,每个生长季写出 303 kB 的逐日文本;Agri-JAX 只运行已验证的逐日模型所含的模块,并返回十条逐日序列。因此这些倍率并非某一个数值内核的加速比。测于 AMD EPYC 9654 的一个绑定核(rorqual,2026年9月28日),每行仅测一次。格子颜色为示意。
现有的 Fortran 实现并不原生支持数组式的批量执行:全局状态与每次运行的文件读写把每个模拟绑定在单个进程上。这是实现方式的属性,而非语言本身的属性。
65 个整季自由运行与 dscsm048 一致:产量、日期、逐日曲线与水量账
- 2.165 个生长季(DSSAT 玉米样例的 58 个处理,以及 AmeriFlux 玉米站点 CA-TPA 的 7 个生长季,共 11 138 天)均为自由运行:土壤水分、蒸发与根系吸水由 Agri-JAX 自行计算,而非读取自 DSSAT。在 59 个有籽粒的生长季中,产量最大偏差为 1.5 %,中位数为 4.0e-5;验收上限为 2 %。出苗、吐丝与成熟日期在 65 个运行中全部一致。逐日 LAI 的 RMSE 最大为 0.0061,剖面土壤水分最大为 0.33 mm,每日水量账闭合到 6.6e-14 mm。
- 2.2一个生长季的逐日对照,UFGA8201 处理 4(灌溉、高氮,即第四幕中标定的处理):LAI、生物量、籽粒质量与剖面土壤水分均与 DSSAT 的曲线重合。最大差异为 LAI 0.0048、生物量 0.54 kg/ha、土壤水分 0.5 mm,均在 DSSAT 自身输出文件的打印取整范围之内。
氮素关闭,CPU 上 float64,参考为 dscsm048 build 486(DSSAT-CSM 4.8.6.0)。只有这一天的各个模块都不产生的内容才取自 DSSAT 回放:有机质模块的残留物记录与逐日土壤性质变化。样例处理与 DSSAT 在其打印分辨率的水平上一致;CA-TPA 生长季在逐日蒸散发与土壤水分上比打印分辨率高 5 至 18 倍。
各模块也分别单独检验过。在 DSSAT 自身的输入上逐日检验,XTRACT 根系吸水在 1.03 个、潜在蒸散发在 4.7 个、土壤反照率在 4.5 个 REAL*4 舍入单位以内。仅运行 CERES-Maize,由 DSSAT 的土壤水分与蒸腾驱动:逐日 LAI 偏差在 0.50 % 以内,生物量 0.63 %,产量 0.030 %,生育阶段逐日一致。
同一任务、同一计时边界:重复调用优势明显,一次性运行则各有胜负
- 3.1在同一计时边界下模拟 10⁴ 与 10⁵ 个生长季。在单个核上模拟 10⁵ 个生长季,DSSAT-CSM 用时 1426 s;Agri-JAX 首次运行 99.1 s,热启动 56.0 s,重复调用 48.9 s。32 核上的倍率为 2.3×、4.1×、22×。在 192 核整节点上,DSSAT-CSM 用时 17.4 s:Agri-JAX 的首次运行较慢(0.85×),热启动快 1.6 倍,重复调用快 25 倍。
- 3.2GPU:定位瓶颈、调整程序布局、核对模型不变。对一块 H100 的剖析显示,每个模拟日约有 490 个短内核,设备空闲 34–45 %。展开层循环(一项按后端选择的执行设置,过程代码不变)后,只剩 60–63 个内核、空闲 2–3 %,重复调用快 3.1 倍(10⁵ 个生长季时由 1.31 s 降至 0.42 s)。代价是编译变长(19 → 67 s)。核对:GPU 与 CPU 相比,65 个运行的阶段日期全部一致,产量相差不超过 1.4e-15;GPU 上展开与循环相比,产量、土壤水分、径流与排水逐位一致。
- 3.3Agri-JAX 在生长季多、核数少时更划算,在同一数组形状下反复调用(标定、敏感性分析、集合模拟)时优势最大:重复调用在所测的每种 CPU 设置上都比 DSSAT-CSM 快 22–29 倍。只跑一次、至多 10³ 个生长季,用 DSSAT-CSM 就够了。表里按任务列出用什么工具、怎么设置。
任务:将 65 个验证生长季复制到 B 个生长季(平均每季 171 天),float64,向主机返回十条逐日序列。Agri-JAX 对每个样本的 7 个参数施加 U(0.9, 1.1) 的扰动;DSSAT 的各个副本不加扰动。硬件:rorqual(Calcul Québec),2 × AMD EPYC 9654(192 核),一整块 NVIDIA H100(主机为 Xeon Gold 6448Y),JAX 0.10.2。“单核”指一个绑定核,“32 核”指在此类节点上申请的 32 核分配,而非 32 核工作站。每个单元格仅测量一次;同一节点上不同进程间,重复调用时间的差异最大可达 20 %。CPU 各行测于 2026年9月28日,H100 各行测于 2026年9月29日。
两边的工作量不同:DSSAT-CSM 在 10⁵ 个生长季时写出 30.3 GB 的逐日文本并运行整个作物–土壤模型,Agri-JAX 返回 1.5 GB 的十条序列。与仅输出汇总的 DSSAT-CSM 相比,单核倍率约减半(重复调用为 15 倍而非 29 倍),整节点倍率不变。H100 所在主机上未运行 DSSAT-CSM,因此 GPU 不给出倍率。未测量,故不给出倍率的情形:10⁶ 个及以上生长季、T4 或 Colab GPU、笔记本电脑。
一次调用即可将品种系数拟合到观测上,并写出 DSSAT 能读回的一行
- 4.1
calibrate(...)读取 DSSAT 玉米试验的处理与观测,以批量联合 CMA-ES 拟合六个品种系数,按候选值写入.CUL行之后的取值挑选最优候选(每个数字 5 个字符,舍入可使日期相差一天),写出该行并用它运行dscsm048。以 UFGA8201 为例:目标函数由 1.015 降至 0.0100,留出处理由 1.046 降至 0.0239,以写出的行运行 DSSAT,产量与 Agri-JAX 相差不超过 2.9e-4。22 个往返检验运行中,全部 22 个日期一致,产量偏差在 0.1 % 以内。 - 4.2可辨识性。仅凭日期、产量、生物量与 LAI,G2 与 G3 沿损失函数的一条弯曲谷地分布:24 次重新标定散布在 G2 355–982、G3 7.6–16.4 之间。加入粒数后,谷地收拢到已发布值附近(G2 831–984,G3 7.5–9.4),留出处理的粒数误差(各种子的最优拟合):−51…−49 % → −7…−6 %。代价是雨养处理 2:其产量误差由 −5 % 增大到 −41 %,原因是模型在水分胁迫下低估了粒数。
- 4.3为什么默认采用联合 CMA-ES。从无噪声的合成观测中恢复已知品种(264 次拟合),225 次拟合达到目标,分阶段方案为 212 次(该方案使用梯度),耗时 135 s 对 210 s。分阶段方案每次拟合所需的模型调用较少(443 次前向与 51 次梯度调用,联合方案为 1008 次前向调用)。
- 4.4梯度按适用范围分级:前向模型已通过验证;部分系数的梯度可用;穿过物候事件的梯度属于实验性质。在一块 H100 上,对 10⁴ 个生长季求籽粒总质量关于五个系数的一次梯度:层循环展开时用时 1.81 s(循环时为 5.02 s),代价是编译 316 s,而循环时为 64 s。
我们不声称标定比 DSSAT-CSM 更快。对上述合成任务,联合 CMA-ES 在 192 核节点上的实测耗时,介于同一节点上理想并行的 DSSAT-CSM 估计值的 1.6 倍慢与 1.2 倍快之间;该估计由实测的每季耗时推算,并非在 DSSAT-CSM 中实际运行标定。损失函数等高线是条件切片(其余系数固定在对实测观测拟合得到的最优值),而非后验分布。
calibrate 目前仅适用于 DSSAT v4.8.6 的玉米样例处理,且氮素关闭;自由运行的逐日模型为这些处理读取的表格不随项目分发。氮素使 DSSAT 产量变化超过 5 % 的处理会被拒绝。
一个过程是带有声明签名的纯函数;换掉一个,同样的检查照常运行
- 5.1一个过程是声明了读写字段的纯函数。三道检查约束的是作者,而不是数值内核:写代码时的 AST 静态检查(AJ001–AJ012、AJ020–AJ021)、运行时对声明写入的核对(
AGRI_JAX_CHECK=1),以及注册时的一致性测试包。每个系数都带有名称、单位、含义与出处。 - 5.2第一条守则,纯函数:读取的一切都是参数,改动的一切都由返回值给出。两个生长季同时写入同一个格子就是冲突,所以状态里每个生长季占一行。
- 5.3第二条守则,用 where 分支:同一天里各个生长季处在不同的生育阶段,所以两个分支都要计算,每一行各取自己的那个。两个分支都必须保持有限,否则梯度会变成 NaN。
- 5.4第三条守则,过程代码中不对土层、日期或样本写循环。沿土壤剖面的递推只写一次,怎样运行由运行时决定:在 CPU 上是循环,在 GPU 上是展开(见第三幕)。
- 5.5只需一行,即可将这一天的土面蒸发由 Ritchie 换为 SALUS。替换后的过程在运行前,要通过对条目声明的核对以及一致性关卡。
- 5.6换入带来什么变化:65 个运行各用自身方法与另一种方法模拟一次,全季土面蒸发的中位数变化为 +26 % 与 −14 %,籽粒产量的中位数变化为 −0.07 % 与 −0.12 %,范围 −27.7 % … +16.1 %。每个换入后的运行中,水量账都闭合到 ≤ 5.9e-14 mm。每种方法按自身运行时都能复现
dscsm048;换入后的运行则是另一个模型。
换入的具体数字见“实测”一节的表格。examples/swap_soil_evaporation.py 无需数据,即可在一个合成生长季上运行这一替换;docs/swapping_a_process.md 与 docs/tutorial_new_process.md 分别说明替换后的检查,以及从零写一个过程。