观潮 · 模式预报与气象 AI 观察

multi_bdy_files 打开后 real.exe 在第 100 个循环失败:上一个边界文件没写出来

2026-10-22

> 一个 50 年、4 公里分辨率的模拟,作者想省的是边界文件的读取时间。他把 multi_bdy_files 打开、配合 bdy_inname 让每个时次写一个独立的边界文件,结果 real.exe 跑到第 100 个循环(共 239 个)时挂掉,报「打开 met_em 文件失败,日期不对或文件不在目录」。关键在于:同一个 met_em 文件在 multi_bdy_files = .false. 下完全能跑通,ncdump 看头部和时次也都正常;而检查运行目录会发现,上一个时次的边界文件根本没被写出来。帖子只到这里,没有回复、没有结论。所以这件事的价值不在答案,而在于它把「报错指向 A,实际嫌疑在 B」这件事摆得很清楚:日志说 met_em 打不开,但同一份日志的上一行刚刚说这个文件「可以接受使用」。

这篇帖子在讲什么事

作者在测一个 50 年、4 公里分辨率的模拟,目标是压 I/O 时间。他盯上的瓶颈是边界文件的读取——测试阶段设成每 3600 秒一次,正式跑会拉到 10800 秒。规模上:10 天的测试算例边界文件约 15.5 GB,而完整的 50 年模拟,每次重启跑要 300 GB 以上。

为了减少边界文件的读取时间,他改了 namelist 两处:

位置 · 设置 · 作用

`&bdy_control` · `multi_bdy_files = .true.` · 每个时次单独写一个边界文件,而不是全部塞进一个

`&time_control` · `bdy_inname = "wrfbdy_d<domain>_<date>"` · 规定这些文件的命名格式

然后跑 real.exe。前 99 个循环一切正常,第 100 个循环失败。

日志里的两句话互相矛盾

失败前后的日志原文(关键行):

```

Domain 1: Current date being processed: 2001-01-05_03:00:00.0000, which is loop # 99 out of 239

d01 2001-01-05_03:00:00 Input data is acceptable to use: met_em.d01.2001-01-05_03:00:00.nc

LBC valid between these times 2001-01-05_02:00:00 and 2001-01-05_03:00:00

d01 2001-01-05_03:00:00 Timing for output 2 s.

d01 2001-01-05_03:00:00 Timing for loop # 99 = 3 s.

Domain 1: Current date being processed: 2001-01-05_04:00:00.0000, which is loop # 100 out of 239

FATAL CALLED FROM FILE: <stdin> LINE: 409

error opening met_em.d01.2001-01-05_04:00:00.nc for input; bad date in namelist or file not in directory

```

第 99 个循环的处理时间是 3 秒,其中输出用了 2 秒;第 100 个循环一开始就 fatal。

矛盾的焦点在这里:报错说的是 met_em.d01.2001-01-05_04:00:00.nc 打不开,但作者的判断是「这个 metgrid 文件没有任何问题」——把 multi_bdy_files 关掉,同一个算例、同一批 met_em 文件可以顺利跑完;用 ncdump 对比头部信息与时次,也看不出异常。

再看一个容易被忽略的细节:日志里 first_date_input 是 2001-01-05_03:00:00,而 first_date_nml 是 2001-01-01_01:00:00。这两者不一致是每个循环都会打印的正常信息(输入数据从当前时次开始,namelist 从模拟起点开始),不是故障信号——但它很容易被当成线索去追。

真正的线索在运行目录里

作者去看了运行目录,发现 real.exe 没有写出上一个时次的边界文件:

> 本应存在的 wrfbdy_d01_2001-01-05_03:00:00,目录里没有。

而同一份日志明确记录了第 99 个循环的 Timing for output 2 s.——也就是说程序认为它成功输出了。

于是作者给出两个互斥的解释,并明确指出两者都说明有问题:

假设 · 含义 · 为什么都成立

同步写 · 程序确实是同步写边界文件的,写这个文件时就出错了,这才是真正的根因,后面的「打不开 met_em」只是次生故障 · 日志的 output 计时是程序自报,不代表落盘成功

异步写 · 程序异步写,还没写完就撞上了另一个至今未知的问题 · 那样 `Timing for output` 就只是提交耗时,不能当成功凭据

无论哪一种,结论都一样:「输出计时 2 秒」不能证明文件写成功了。

这个帖子留下的可复用判断

原帖没有结论,也没有人回复。但把它当成一份排障记录来看,它给出了几个可以直接搬用的判据:

判据一:报错指向的文件,先证伪再追。 报错说 met_em 打不开,作者用「关掉开关就正常」+「ncdump 头部正常」两步把它排除了。这一步做得对——否则会花大量时间在 metgrid 侧找一个不存在的错误。

判据二:把「日志说成功」和「磁盘上有文件」分开验。 本次故障的核心就在这条缝里:Timing for output 是程序自报的耗时,不是写盘成功的证据。要确认,得去目录里数文件、看大小。

判据三:算规模,判断是不是撞上了大小/时间边界。 这里有两个数字值得放在一起看:239 个循环的总量、以及单个边界文件在正式跑时的体积。第 100 个循环这个位置本身未必有物理含义,但当「前 99 个循环都正常、第 100 个必挂」这种整数位置反复出现时,值得怀疑是某个累积量(文件句柄、缓冲区、计数上限)而不是数据本身。

判据四:单帖无回复,不要当成已知问题。 这个帖子只有一帖、没有回复、没有标为解决。它在论坛上停留的状态是「有人遇到了,还没人确认原因」。

作者承认的限制

一句话判断

这份帖子的用处不在于解决 multi_bdy_files 的 bug,而在于它示范了一个正确的怀疑顺序:报错文件先证伪、日志计时不能当写盘证据、整数循环位置反复出现时往累积量上想——三条都做到了,只是这一题最后没解出来。

在观潮中打开(含配图与交互)→