观潮 · 模式预报与气象 AI 观察
multi_bdy_files 打开后 real.exe 在第 100 个循环失败:上一个边界文件没写出来
> 一个 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 个必挂」这种整数位置反复出现时,值得怀疑是某个累积量(文件句柄、缓冲区、计数上限)而不是数据本身。
判据四:单帖无回复,不要当成已知问题。 这个帖子只有一帖、没有回复、没有标为解决。它在论坛上停留的状态是「有人遇到了,还没人确认原因」。
作者承认的限制
- 帖子没有结论。原帖在给出两个假设之后就结束了,既没有后续验证,也没有官方回复。所以「为什么第 100 个循环失败」这个问题,到今天仍然没有答案。
- 没有做过对照实验的细节。作者说关掉
multi_bdy_files就能跑通,但没有给出两次运行的完整 namelist 差异;也没有说明是否试过更短的模拟、更少的分域,或者换一个起始时间。 - 假设二里的「另一个未知问题」始终没有被定义。异步写这个分支实际上是把问题推给了一个未命名的原因,作者自己也用了「至今未知」这样的说法来描述它。
- 没有提供磁盘侧的量化证据。目录里缺文件是定性观察,帖子里没有给出失败时目录的文件清单、各文件大小,也没有
rsl.out.000之外的日志。
一句话判断
这份帖子的用处不在于解决 multi_bdy_files 的 bug,而在于它示范了一个正确的怀疑顺序:报错文件先证伪、日志计时不能当写盘证据、整数循环位置反复出现时往累积量上想——三条都做到了,只是这一题最后没解出来。