关于数值天气预报业务系统支撑软件工具发展方向的一些想法
声明:本文仅代表笔者个人观点,文章中引用的相关材料仅用于探讨和交流,不能作为最终事实依据。 关于数值天气预报模式系统的相关信息,请以官方发布的信息及经过同行评议的论文为准。 如有任何疑问,建议查阅权威资料或咨询相关领域的专家。
本文受 ECMWF 技术文档《Software Strategy and Roadmap 2023–2027》启发而撰写,大量内容来自对该技术文档内容的重组。 笔者对该技术文档的翻译参见《论文阅读:ECMWF软件战略和路线图2023-2027》
本文聚焦数值天气预报业务系统 (NWP) 使用的一些支撑软件工具领域,介绍 笔者个人 对 NWP 支撑软件工具相关领域未来一段时间 (1-3年) 发展方向的一些想法。
范围
本文仅讨论软件工具包,不涉及系统平台。
软件工具包一般作为一个功能组件可以集成到某个系统或平台中,例如:
- NetCDF 库
- wgrib2
- ecFlow
系统或平台可以提供某种产品或服务,例如:
- NWP 业务运行系统
- NWP 业务监控系统
- NWP 中试试验平台
- NWP 数据管理平台
指导原则
参考 ECMWF 软件发展战略文档中的指导原则。
- 软件可重用。软件可以在多种环境中复用,比如超算、云平台、个人工作电脑、Jupyter笔记本等
- 软件组件化。将通用基础功能从各个工具库中抽取出来形成独立的工具组件,方便集成到其他工具中。注重工具与 Python 的集成
- 数据标准化。制定并遵循统一的标准数据结构,提高软件工具之间的互操作性
- 版本管理。通过版本库规范开发流程,探索协作开发途径,扩大软件工具的使用范围
- 开源发布。提供测试用例和用户手册
发展方向
软件工具领域
场景
软件工具有两个使用场景:
- 模式软件
模式软件是直接应用到地球系统数值预报模式 (ESM) 业务系统中的软件。
示例:
- 观测资料检索工具库
- GRIB2 编解码工具库
- 绘图工具包
- 支撑与分析工具
支撑与分析工具是支撑地球系统数值预报模式研发的软件工具,也包括对模式数据进行分析的工具。 这类工具可能间接应用到业务系统中,例如作为某个工具引用的包。
示例:
- CMADaaS 发布的 music-sdk
- 数据准备工具库 reki
领域
本文对 NWP 支撑软件工具分为如下领域,按照当前的开发进展进行分类。
现有领域:已有完整解决方案,并应用在业务系统中
- 数据编解码
- 观测数据检索(与预处理)
- 可视化
- 数据存储
进行中的领域:正在开发,尚未应用到业务系统中
- 工作流调度
- 交互分析工具
未开展的领域:尚未开展工作(本文不涉及)
- 观测资料预处理
- 数据分发
- 后处理
软件栈
现状
当前 NWP 有两种软件栈:编译软件栈和 Python 软件栈。 下面列出两种软件栈的典型工具。
编译软件栈
Fortran
- NWP 数据编解码工具
- CMADaaS 观测资料检索工具 (Fortran 版)
C/C++
- 日期计算工具 (smsdate)
GOLANG
- 数据查找 (nwpc-data-client)
- 台风报文检索 (nmc-typhoon-db-client)
- Slurm 作业查询 (slurm-client-go,个人使用)
Python 软件栈
- CMADaaS 观测资料检索工具 (Python 版)
- cedarkit 工具套件 (尚未应用到 NWP 业务系统中)
Python 软件栈包含大量内部使用的工具。
绘图工具
- 区域集合系统绘图包
- 全球集合系统绘图包
- 区域台风系统海雾绘图包
- 全球模式系统部分绘图脚本
检验诊断工具
- NWP 模式检验评估工具
动机
构建以 Python 包为中心的基础软件栈。
人生苦短,我用 Python
人工智能时代最火的语言莫过于 Python。在气象大模型已经成为 ECMWF 业务系统并提供实时数据服务的现在,Python 软件工具变得越来越重要。 虽然 Python 工具有诸多问题,尤其是部署环境复杂的版本依赖关系,但在人工智能的热潮中,Python 已然成为气象领域不可获取的专业知识,每个从业者都或多或少接触过 Python,用过 Python,甚至写过 Python。 是时候构建以 Python 包为中心的基础软件栈,利用 Python 庞大的用户社区降低专用软件包的维护成本,让更多从业人员参与到基础软件工具的开发工作中。
同时,编译软件栈在效率和部署上依然有 Python 不可比拟的优势,尤其是编译软件栈可以更好地集成到 NWP 核心模式组件中。 需要对编译软件栈进行梳理,考虑将用于非模式核心组件的编译软件改为用 Python 实现,比如画图前的数据处理计算。 对于用于模式核心的软件包,考虑继续使用 Fortran 实现的可维护性问题,探讨是否使用 C/C++ 等具有更庞大用户社区的编程语言实现。
编写标准数据结构规范,增加工具间的互操作性。
NWP 支撑工具最终都与 NWP 数据打交道。 每个工具都构造了一套适合自己使用的数据结构,比如:
- reki 使用
xarray.DataArray
保存网格点数据 - 区域集合系统绘图工具使用
numpy.ndarray
保存网格点数据 - music-sdk-python 使用自定义的 class 保存格点数据及其元信息
虽然各个工具库的数据结构有所区别,但大多使用了 Python 科学计算社区的通用开源工具库表示数据,比如 numpy.ndarray
,pandas.DataFrame
,xarray.DataArray
等。
为了提高工具之间的互操作性,需要制定一个统一的 Python 数据结构规范,为不同类型的数据规定数据存储形式和元信息表述方式。
比如 cedarkit 工具套件中采用一种方案:
- 网格点数据:
xarray.DataArray
,坐标维度包括 latitude、longitude、step、time、valid_time 等 - 表格数据:
pandas.DataFrame
制定开源工具发布策略,使用版本控制系统,探索协作开发机制。
笔者是坚定的开源鼓吹者,一直以来都将不涉及核心组件的个人工作项目开源发布 (cemc-oper 组)。 笔者始终认为 NWP 支撑软件工具应该开源发布,只有加入开源社区才有可能将软件工具推广到更广泛的用户中。 强烈建议将开源当成软件工具的一个可选项,推动新立项的 NWP 支撑软件工具尤其是新开发的 Python 基础工具库从 内部共享 逐步走向 开源,将 Python 工具发布到 GitHub 等开源仓库,并发布到 PyPI 和 conda-forge 等软件仓库。
软件开源不止在于让更多的用户使用,同时也能吸引更多开发者持续完善软件项目。 与 ECMWF 软件战略文档提到的避免单人开发项目类似,建议从内部团队开始探索协作开发机制,在时机成熟后逐步扩展到整个公共社区。
笔者 充分理解和尊重 各个工具库开发人员/团队选择适合自己的项目发布策略,也 不会建议 编译软件栈开源发布,更 不会建议 现有工具走向开源。
撰写测试用例、文档,推广工具使用。
一个完整的开源项目除了实现既定功能的代码外,还需要包括大量测试代码,比如可以在个人工作电脑开发环境中运行的单元测试、在超算平台中使用实际业务数据运行的集成测试等。 笔者每次想要为已有代码编写测试都会因为无从下手而最终放弃,又没能学会测试驱动开发,所以笔者开发的项目大多没有测试代码。 缺少测试代码最大的问题在于无法快速确定修改代码是否影响正确结果,导致不敢轻易修改代码,从而影响软件本身的可持续发展。 建议至少了解测试驱动开发的基本思想,尽量为软件工具项目编写单元测试,在不容易实现的情况下编写在特定环境特定条件下运行的集成测试。 同时,考虑使用类似 GitHub Actions 等持续集成工具,将软件工具包自动发布到软件仓库。
开源项目另一个重要的方面就是用户文档。 即便测试代码可以当成一种最直观的文档,单独撰写的用户文档更容易让新用户入门。 建议为工具软件项目撰写用户使用文档,充分利用 Sphnix 等文档生成工具根据注释为 API 提供使用说明。
建议将文档发布到互联网平台。
- 可以自动构建的文档可以发布到 readthedocs 等平台。例如 reki 文档
- 如果文档需要使用内部数据,无法使用互联网平台自动生成,可以在内部环境生成后,将文档上传到 Github 平台,再发布到 Netlify 等平台。例如 cedarkit 使用指南
推荐内部共享的工具通过以上两种方式将文档发布到互联网平台,便于内部用户查看。
行动计划
构建 Python 工具栈 cedarkit,用于对地球系统数值预报模式数据的分析与可视化。 将 cedarkit 系列库推广到 NWP 系统的 Python 程序中。
持续开源 cedarkit 工具套件,吸引大家参与到开源软件的开发中。
数据编解码
数据编解码分为格点数据和观测数据两个子领域。
格点数据
现状
Fortran 软件栈
GRIB 编解码工具库
特点
- 自主知识产权,不依赖其他 GRIB 编解码库
- 使用 JPEG2000 压缩算法,压缩比例高
- 支持多种类型要素的编码,支持多种 NWP 系统,包括确定性模式、集合模式和专业模式等,应用在所有 NWP 业务系统中
关注点
与 Python 工具链集成。 现有 Python 软件栈通常使用 ecCodes (eccodes-python, pygrib) 或 wgrib2 (pyNIO) 解码。 使用较多的开源软件 pygrib 和 eccodes-python 均依赖 ecCodes C 共享库。 可以探索在 Python 中调用 Fortran 共享库的方式,例如 numpy 使用的 f2py 等。
解码速度。 当前 GRIB2 数据使用 JPEG2000 压缩,优势是压缩后的文件最小,劣势是解码需要大量时间。 例如在笔者个人工作电脑上区域一公里模式单个要素解码需要 20 秒左右。 在存储成本和传输成本日趋下降的情况下,解码速度远比文件大小更影响用户的使用体验。 如果通过更换压缩算法能将解码速度降低一个数量级,非常有必要替换现有的 JPEG2000 压缩算法。 正在尝试引入新的压缩算法,降低压缩比例,换取更快的解码速度。
要素编码。 要素编码信息在编译过程中内置到 Fortran 程序中,能有效节省解析文本的时间,但不方便动态修改,修改要素的编码需要重新编译。 ecCodes 支持运行时解析保存要素编码的 definition 文件,同样也支持将 definition 文件编译到程序中。 建议考虑引入运行时解析的要素编码来增加工具的扩展性。
与开源项目的集成。 开源项目通常不依赖其他非开源项目,但可以将非开源项目作为一个选项。 比如 cedarkit-maps 内置了中国区域底图,也通过内部项目 cemc-meda-data 支持内部使用的中国区域底图。 与 Python 工具链集成 也可以采用类似的方案,将内部工具库作为一个选项。 但这就涉及到一个问题,也是整个专用软件栈需要面对的问题,为什么不直接使用 Python 科学计算领域的开源软件? 笔者也不好回答。
Python 软件栈
reki
特点
- 提供便捷使用的 API 接口
- 支持 GRIB2 数据,少量支持 NWP 用到的文本类型观测数据
- 提供少量数据操作函数,如区域裁剪、插值
- 内置 WGRIB2 和 CEMC 要素清单
关注点
- 文档。 当前文档只有“开始使用”一个完整章节,提供基本用法说明,缺少更详细的使用说明。 大量功能隐藏在代码中,没有通过文档直观展示给潜在用户。
- 测试用例。 当前测试仅能在特定条件下运行 (WSL 环境中挂载归档 NWP 数据产品的 NAS 存储)。 因为新的 NAS 存储不支持手动挂载,需要将测试用例的运行环境迁移到 HPC 平台。 同时考虑互联网平台运行测试用例的可行性,比如使用其他 WMC 中心公开发布的数据作为测试数据。
- 数据浏览与探查。
reki 当前提供的 API 适合在已知 GRIB2 文件要素清单的情况下使用,通过给定具体的检索条件返回需要的要素场。
但更多时候我们不了解 GRIB2 文件的内容,或者对 GRIB2 格式不太了解,想要查看文件中包含哪些要素场,此时就需要工具提供对数据文件的浏览和探查功能。
例如,命令行工具
grib_ls
、wgrib2
都支持打印要素场清单列表。 reki 也需要开发类似的功能,扩展工具的使用场景,参考 earhtkit-data 工具库的相关函数,进一步与 Jupyter 笔记本集成。 - 要素清单。 reki 内置 CEMC 要素清单,支持将 CEMC 要素名转为 GRIB2 对应的要素编号,但是不支持自动设置层次等其他属性。 比如 t2m 表示 2 米温度,API 中应该给定该要素名称就能定位到 2 米温度场,而当前 reki 的 API 还需要提供层次类型 (heightAboveGround) 和层次值 (2)。 为了实现上述功能,需要重构 GRIB 消息筛选逻辑。
- 多要素场支持。 reki 主要针对从单个文件中加载单个要素场开发,也支持加载同一要素的多个层次,但不支持加载同一个文件中的不同要素,也不支持从多个文件中加载要素场。 需要完善数据加载功能,针对不同需求开发 API 接口。 同时,考虑实现延迟加载功能,支持大规模数据集。
- 数据操作。 当前数据操作函数过少,无法覆盖通用需求。 建议参考 esmvalcore 等开源项目,提供基础数据操作功能。 并将气象领域相关的算法逐步加入到 cedarkit-comp 项目中。
- 数据源。 仅支持本地可访问文件系统的数据 (POSIX 协议),但更多数据保存在各类数据平台中,无法直接访问。 需要扩展工具支持的数据源,至少接入 CMADaaS 和 GODAS 等远程数据平台。
- 开发方式。 reki 项目当前仅由单人开发,尚未形成开发团队。 尽管为了项目可持续发展应该避免单人开发的项目,但笔者尚未找到合适的团队开发方式。 这也是本文面临的一个重要问题,将在总结章节中简单分析。
动机
项目
缺少数据标准说明文档,缺乏要素清单文档。
不同项目之间的互操作性往往通过数据体现,非常有必要编制数据格式规范,为所有项目提供统一的指南。 建议为 Python 工具栈提供数据结构规范,使数据可以在不同项目之间任意流动。
为了让不同工具都遵循统一的数据标准,同时方便用户找到感兴趣的要素,建议提供要素清单文档,类似 ECMWF 的要素数据库 (ecmwf parameter database)。 工具可以很方便地从要素清单文档生成内置到项目中的要素清单。
reki 缺少测试用例、说明文档
一个开源项目想要吸引新用户,就要让用户相信该项目能持续发展下去。 而完整的测试用例和详尽的说明文档则是证明该项目未来前景的强有力信号。
有说明文档,就能显著降低用户的学习成本,让用户能快速了解软件工具的主要功能。 建议投入足够的精力编写 reki 用户文档,详细介绍 reki 提供的各种功能。 编写可以在 HPC 平台上运行的 Jupyter 笔记本格式的指南类项目 (例如 JupyterBook),提供与 NWP 数据相关的更多操作说明,例如如何加载 GRIB2 文件中的每条 GRIB2 消息。
详尽的单元测试用例能吸引潜在开发者尝试对软件进行修改,而无需担心破坏软件现有功能。 建议重构 reki 项目的单元测试用例,支持在 HPC 平台上的快速运行,并考虑使用公开数据集进行 CI 测试。
实现
JPEG2000 解压缩耗时过长
正如上文关注点中提到的,虽然 JPEG2000 提供了高精度的有损压缩和高压缩比,但代价是 JPEG2000 解码时间过长,并且在存在一定的专利风险。 过长的解压缩时间也影响了公里级别区域模式数据的使用,NWP 产品平台对公里区域模式数据进行预处理,存储中间数据用于支撑实时显示,而其他模式因为网格点较少,解码时间比较快,无需单独存储中间数据。 如果能提高解压缩速度,则会显著改善高分辨率模式数据的使用体验。
ecCodes 使用 OpenJPEG 和 Jasper 开源库提供 JPEG2000 编解码功能,但 ECMWF 发布的 GRIB2 数据使用编解码性能更好且没有专利问题的 CCSDS 压缩算法。 建议考虑采用其他解码速度更快的压缩算法。
Fortran、Python 与 C++
数值预报模式等数值模拟软件主要使用 Fortran 实现。 当前 NWP 系统主要由气象领域专家开发,预计未来会有更多不同领域的专家参与系统开发,下一代 NWP 系统可能会引入更多的编程语言。 ECMWF 正在开发的下一代模式中使用了基于 Python 的领域特定语言 (GT4Py) [1],并在一篇通讯文章中指出吸引和保留愿意从事“旧” 软件框架和编程语言 (例如 Fortran) 相关工作的软件工程师未来将会变得更加困难 [2]。 CMA 正在研发的下一代大气数值模式使用了面向地球系统数值预报的耦合器 C-Coupler3,该项目使用 C++ 实现 [3]。
NWP 支撑软件大多使用其他语言实现。 比如 ECMWF 发布的一系列软件大多使用 C/C++、Python 等编程语言实现。 非气象背景的开发人员通常对 Fortran 不了解,建议考虑是否将 Fortran 支撑软件转为使用 C++ 或 Python 实现。
注:GitHub 中 ecmwf 组使用的主要编程语言排序,数据来源 https://github.com/ecmwf
编程语言 典型项目 Python anemoi-core C++ eccodes Jupyter Notebook pyflow Shell anemoi-configs TypeScript build-package
reki 仅支持在已知要素清单的情况下查找要素场
开发 reki 项目 (前称 nwpc-data) 的最初目的是为一个内部检验工具提供从 NWP 系统 GRIB2 数据中加载特定要素场的函数,后续 reki 项目也应用在全球模式系统的产品制作任务中,都是在已知 GRIB2 数据要素清单的情况下查找要素场。
除了上述批处理任务外,类似 reki 的数据准备工具库还大量用于对数据的探索性分析,尤其是在不知道数据要素清单的情况下使用工具库了解数据的概要信息。
earthkit-data 等工具库提供了大量用于探索数据的函数,比如 earthkit-data 提供 ls()
head()
tail()
等函数用于列出数据条目,describe()
用于提供汇总信息。
为了提高数据准备工具库的使用范围,Python 工具库需要提供数据探查相关功能。
reki 不支持 ODB 格式的观测数据
reki 主要提供对 GRIB2 数据的支持。 对于 NWP 系统使用文本格式保存的预处理后观测资料,reki 仅提供少量支持。 reki 还不支持 NWP 系统部分观测资料自定义的二级制观测资料格式。
下一代 NWP 系统将使用由 ECMWF 制定的统一观测资料格式 (ODB2),非常有必要在 reki 中新增对 ODB 格式数据的支持,可以直接利用 ECMWF 发布的开源项目 pyodc 实现。 更详细的讨论请查看“观测数据”章节。
需要整合多个数据数据来源,形成新的 cedarkit-data 库
reki 仅支持从本地文件加载数据,没有考虑多种数据源。 目前 NWP 系统现在可用和未来也许会用的数据源包括:
- 本地 (Local)
- 超算
- NAS 存储
- CMADaaS NAS 挂载
- CMADaaS API 接口
- 数据平台 (GODAS)
建议参考 earthkit-data 项目,将多种数据源整合到一个软件项目中,提供一致的访问接口。 建议考虑开发新的 cedarkit-data 库,整合 reki 和其他数据源获取工具库。
开源
面向公开社区的开源
NWP 系统使用了大量的开源项目,是时候回馈开源社区并赢得开源社区影响力了。
Python 开发的支撑工具项目非常适合开源,包括 reki 在内的 cedarkit 工具栈从一开始就被设计成一组开源项目。 建议新开发的 Python 支撑工具考虑是否从有限范围分享代码改为公开社区开源。
联动
编译工具栈和 Python 工具栈之间缺少联动
内部编译工具栈没有直接提供 Python 调用接口,当前读取 GRIB2 文件使用的 Python 接口大多依赖 eccodes (eccodes-python, pygrib, reki)。 在其他类型的某个任务中,Python 脚本通过 subprocess 库调用编译后的可执行程序,类似 shell 的胶水语言形式。 建议考虑为内部编译工具栈添加 Python 支持的可行性。
reki 库尚未推广到业务系统和其他内部工具中
reki 库没有在内部进行过推广,仅应用在全球模式的部分派生数据产品制作任务中,前身 nwpc-data 应用在内部的检验工具中。 为了项目的可持续发展,必须要考虑项目的推广问题,更多用户使用才能带来更多的需求,更多的需求也为开发团队带来更多的责任,促使开发团队持续改进工具。 推广项目还需要用户文档和使用示例,建议投入足够的精力开展编写代码之外的工作。
资源
reki 库属于单人开发探索项目,开发 (人力) 投入不够
一个可持续发展的支撑工具软件需要遵循与用户的约定,及时响应用户需求,修复软件 BUG,并开发新功能。 建议为 reki 库规划开发路线图,适时发布更新版本。 并尝试探索团队协作开发的合适途径,形成开发团队,避免单人开发项目。
行动计划
编写格点数据标准规范文档,包括数据格式说明和要素清单。
完善 reki 库,开发数据探索功能,增加对 ODB 格式的支持。
发展 cedarkit-data 库,集成多个数据源访问库,为 Python 工具库提供标准的数据结构对象。
考虑开发 C++ 版格点数据编解码库。
观测数据
现状
NWP 系统对原始观测资料进行预处理,生成同化系统能够识别的数据,也就是预处理后的观测数据。 当前 NWP 系统中预处理后的观测数据大量使用自定义格式。典型的自定义格式包括:
- 文本格式,表格形式一般采用文本格式
- 常规观测
- 台风报文
- 常规观测
- 二进制,格点数据使用二进制格式
- 卫星数据预处理后的资料
关注点
- 说明文档。预处理后的观测数据格式缺乏统一的标准,也缺乏详细的说明文档。
- 解析。多数自定义的格式仅能通过查阅系统源代码才能了解具体的资料格式,不利于在其他应用中解析,也不利于协作开发。
下一代 NWP 系统开始使用 ECMWF 使用的 ODB2 作为观测数据的标准格式。
特点
- 下一代 NWP 系统的同化模块已附带示例数据
- Fortran 代码中使用 ECMWF 的 odb 库解码
关注点
- ODB 应用尚在早期阶段,缺乏格式说明文档
- 可以借助示例数据开展数据编解码的前期开发工作
- 缺少 Python 使用示例,可以使用 ECMWF 发布的 pyodc 库
动机
ODB 格式数据编解码工具
当前 ODB 格式数据的编解码使用 ECMWF 的开源库 (odc) 实现。考虑是否自行开发 ODB 解码库。
引入 ODB 格式的最大因素是支持 SQL 查询。自行实现 SQL 查询引擎太难,是否可以使用现有开源项目来实现。 例如,可以尝试基于 SQLite 开发类似 ODB 的新格式。
Python 接口
ECMWF 的 pyodc 库支持 Python 编解码 ODB 格式。 建议在 reki 中通过调用 pyodc 库支持 ODB 格式数据。
行动计划
制定观测数据格式标准规范。
在 reki 中新增对下一代 NWP 系统使用的 ODB 格式数据支持。
开发 C++ 版本的类似 ODB2 格式的编解码库。
远期:兼容 ODB API 接口,底层使用其他方式实现。
联动
- 观测数据检索(与预处理):检索程序使用编码包保存检索结果
- 交互分析工具:reki 使用解码包解析 ODB 格式的观测资料
观测数据检索(与预处理)
现状
Fortran
cmadaas-realtime 是 NWP 系统使用的 CMADaaS 检索库,应用于绝大部分检索场景,包括常规观测、雷达观测、卫星数据、台风报文等等。
特点:
- 实现。Fortran 编程语言,调用 CMADaaS 的 MUSIC Fortran SDK,源代码主要通过外协项目由第三方实现
- 历史沿革。专为 NWP 模式系统开发,直接生成模式系统可以识别需要的数据格式。从 CIMISS [1] 延续到 CMADaaS。
- 可配置。INI 格式配置文件,提供灵活定制功能。配置文件内容包括用户账户信息、每类资料的检索参数等。
- 命令行参数。命令行参数传递经常变动的信息,例如观测时间、时间窗等,不经常变动的参数保存在配置文件中。
问题:
- 配置。配置文件部分参数不够直观,大量参数直接和 MUSIC 接口强相关,对 MUSIC 接口不了解的用户很难理解参数具体用途和可选参数值。 资料相关配置和账户配置保存在同一个文件中,不利于软件分发,需要将账户配置拆分到单独的文件中,或者通过命令行传递。
- 模块化。模块化拆分不够。
原始观测资料数据检索与对原始数据的处理混合在一起,很难进行调试,比如台风资料处理的全部逻辑放在同一个函数 (
typhoon
) 中。 核心流程和不同资料的处理实现混在一起,主流程 (cimiss_main.F90) 中大量使用 if 语句判断检索的资料种类 (type_ob_in
),不利于后续扩展。 需要重新设计软件架构,实现流程逻辑和具体算法的分离,引入软件设计原则,降低新增资料的接入成本。 - 维护。最早由研发部门维护。目前转为业务部门维护,研发部门提供技术支持。 因业务部门使用 Fotran 人员较少,开发已停滞,缺乏专业人员后续维护,发现 BUG 没法按时修复,仅修复少数 BUG。
- 版本管理。研发部门使用 Perforce 作为发布库,和 NWP 模式保持一致。 业务部门基本不使用版本管理工具开展支撑软件工具开发,接手项目后改为使用 HPC 文件系统目录作为版本发布渠道,导致一定程度的版本混乱。 尤其在新老超算平台切换后,很难确定每个系统使用了哪个版本的程序,更新台风报文检索源代码后只能为其单独保存一份检索程序,而无法直接替换整个系统的检索程序。
Python
get_obs/Python
特点:
- 实现 cmadaas-realtime 项目没有覆盖的资料检索功能,主要针对推送到 COMMONDATA 的观测资料,使用下载方式从 CMADaaS 获取数据
- 应用到区域 NWP 系统的资料检索任务,作为卫星、雷达等资料除推送 HPC 之外的替代获取方式,并应用到省局区域模式的检索任务中
问题
- 模块化。每个资料对应一个 Python 文件,不同 Python 模块之间缺乏共享
cmadaas
特点
- 实现常规观测的检索,重新实现 cmadaas-realtime 的各项功能
- 面向下一代 NWP 系统开发的观测资料检索工具库
- 目前处于测试阶段,可以替换台风报文检索
问题
- 模块化。当前所有功能都包含在一个 Python 文件中,利于部署应用,但不一定利于后续维护
- 实现。与 cmadaas-realtime 类似,不同类型资料逻辑通过 if 语句区分
[1] 熊安元, 赵芳, 王颖, 张小缨, 高峰, 邓莉, 谭小华, 马强. 全国综合气象信息共享系统的设计与实现. 应用气象学报, 2015, 26(4): 500-512.
动机
开发目标
无论是 cmadaas-realtime 还是正在开发中的 Python 检索工具库,都仅针对业务系统通过命令行 CLI 方式检索观测资料文件的场景设计,缺乏可供其他库调用的 API 接口,不方便与其他 Python 工具库集成。 需要重新制定观测数据检索类工具库的开发目标,从面向 NWP 系统开发命令行检索工具过渡到提供研发与业务通用的观测资料检索工具库,命令行检索仅是检索工具库中提供的一个子功能。
代码实现
当前软件项目的实现至少存在下面情况中的一种:
- 针对不同资料的处理混合在单一文件中
- 原始数据检索,和对原始数据的处理混合在同一个函数中
从长远维护角度出发,需要引入模块化思想,区分逻辑与实现算法,尽量在不同资料的检索功能中共享代码,同时保证不同资料检索的独立性,降低新增观测资料检索代码的成本。 cmadaas-realtime 使用命令行参数与配置文件相结合思路也应该继承到新开发的 Python 工具库中,用配置文件提高工具的灵活性,并实现账户配置信息与观测资料检索配置信息分离,方便软件分发。
开源
当前项目均缺少测试用例和用户文档等开源项目的支持部分。 缺少测试用例,在修改代码后就无法快速验证修改是否对已有结果产生不利影响。 缺少用户文档,无法直接了解从原始数据到工具输出的观测数据之间都进行了哪些操作,以及为什么要做这些操作,只能从代码中进行推断。 所以,非常有必要为项目编写测试用例和用户文档。
无论是 NWP 系统使用的 Fortran 版检索工具,还是正在开发的 Python 版检索工具,均依赖 NMIC 发布 CMADaaS MUSIC SDK。 该 SDK 属于专有软件,无法开源,因此依赖该 SDK 的软件也同样无法开源。 现有关于 CMADaaS 数据检索的开源项目大多通过 URL 方式获取数据,均不依赖 MUSIC SDK。 因此,需要评估观测数据检索工具是否要继续依赖专有的 MUSIC SDK。
行动计划
用 Python 开发 (观测) 数据检索工具库
定位
- 作为数据准备工具库中数据来源组件的一部分
功能
- 数据源。检索 CMADaaS 数据
- 接口。提供 API 接口,API 设计符合使用习惯。参考 ECMWF 的 MARS 库,检索条件使用 key-value 形式,和 CMADaaS 接口类似,命名更容易理解
- 未来功能。检索模式产生的观测资料数据,比如预处理后的观测资料文件 (文本或 ODB 等)
实现
- CMADaaS 检索功能与具体资料检索分离
- 配置文件中资料配置和账户配置分离
- 是否使用原生music-sdk?可选 URL 方式或采用 nuwe-cmadas-py 项目自行实现的检索接口。
注:nuwe-cmadaas-py 项目涉及对 API 调用的逆向工程,笔者正在评估该项目的版权风险,未来可能会重构该项目,使用 URL 方式检索数据,建议开源项目使用没有风险的 URL 方式
派生库 (或集成到工具中)
- 业务系统天擎检索命令行工具。根据该工具库开发命令行检索库,附加业务系统需要的对原始数据进行处理的功能
相互作用
- 数据编解码:命令行检索工具生成 ODB 格式的观测资料,使用 ODB 编码功能
- 交互分析环境:作为数据准备包的数据来源,提供 CMADaaS 数据检索
- 观测资料预处理:作为数据来源
- 数据存储:作为观测资料库的数据来源之一
可视化
现状
关于可视化相关工作的更详细现状,请参考《绘图工具库cedarkit-maps介绍》“背景”章节。
业务系统
NCL
- GFS、MESO 主要使用的绘图工具
- 开发绘图包 ncllib
- 针对省局部署需求开发了 MESO 绘图包
GrADS
主要应用在 TYM、GEPS 等系统中,多用于研发诊断过程中。
Python
新开发的图片产品均使用 Python 绘制。
区域集合系统绘图工具库
- 配置文件控制绘图种类
- 单独 Python 文件控制绘图样式
- 自适应集合成员个数,自动忽略缺失数据的集合成员
- 模块化设计,GRIB2 数据解码、数据计算、绘图、结果数据输出
新版全球集合系统绘图工具库
- 类似区域集合系统绘图工具库
- 单独 Python 文件控制绘图样式
- 一个绘图类型一个 Python 文件
- 自适应集合成员个数,自动忽略缺失数据的集合成员
区域台风系统海雾产品、WMC 网站图片产品等其他图片产品也同样使用 Python 绘制。
Web平台
基于 MOAP 构建 NWP 产品展示平台。关于 MOAP 的详细介绍请参考如下文献:
胡争光, 薛峰, 金荣花, 等, 2020. 智能网格预报应用分析平台设计与实现. 气象, 46(10): 1340-1350. DOI: 10.7519/j.issn.1000-0526.2020.10.008.
Python绘图包
cedarkit-maps
特点
- cedarkit 工作套件组件
- 内置 NWP 业务系统使用的图片板式
- 使用 reki 作为数据加载工具,也支持其他数据准备工具库
派生工具
cedar-graph
- 业务图片包
- 内置业务图片产品
- 与具体的业务系统数据无关
cemc-plot-kits
- 业务绘图工具包
- 对接业务系统数据
- 提供命令行、Python 函数接口
- 支持批量绘制
动机
通用绘图工具
不同系统使用的 Python 绘图工具独立开发,缺乏统一的通用绘图工具库。 分散开发导致同一个功能在不同绘图脚本中使用不同的第三方依赖包实现,甚至需要为某个绘图脚本准备特定版本的 Python 运行环境,严重影响 NWP 系统迁移新超算环境的效率。 独立绘图脚本也导致不同脚本之间无法相互借鉴优点,并会带来较高的维护成本。
当前 NWP 业务使用的绘图工具或脚本仅面向实时业务系统图片产品需求而开发,没有应用到其他任务中,比如模式研发、诊断评估等。 因为业务系统通常不会频繁变更,一个工具如果只在业务系统中应用会影响开发者持续优化实现的积极性。 而如果不对工具进行持续优化,工具将很快从积极维护的项目退化为遗留代码,充斥大量无意义代码和注释掉的历史代码,只要能用就不会再看一眼。
建议对 NWP 系统现有 Python 绘图脚本进行整合,形成一个通用的绘图工具,支持实时业务系统,也支持模式研发、诊断评估等其他工作任务。
绘图脚本中计算和绘图混在一起,缺少代码共享
不同 Python 绘图工具中均或多或少引入模块化的思想,比如区域集合系统绘图包将实现不同功能的函数拆分到不同模块中,全球集合系统绘图包使用不同的函数实现不同功能。 但分散的开发模式依然会带来跨项目之间的重复性。 现有绘图工具通常将一个绘图任务看为一个整体,包含数据准备、数据计算和可视化三个步骤。 实际上,绘图与计算完全可以分离,绘图库只考虑绘图,而计算库实现计算,类似 geocat-comp 和 earthkit-comp。
建议为气象相关算法单独创建一个计算工具库,绘图脚本在需要执行某种计算时调用该库实现。
绘图工具对接超算平台本地存储的业务系统数据,需要扩展数据源,提高工具的通用性
扩展工具库使用范围的一种方式就是对接多种数据源。 随着 NWP 系统模式空间分辨率提高,超算平台本地存储数据的形式可能会发生显著的变化。 因此绘图工具需要提供对接不同来源数据的接口,而不能将本地文件系统作为数据的唯一接入方式。
cedarkit-maps系列工具
cedarkit-maps 需要提供灵活定制功能,适应多种需求,比如
- 图片板式:如何使用自定义的图片板式
- 图形样式:如何使用新的色表、层次值等
- 小时级、分钟级数据:支持不同种类的数据,不同时间单位的数据如何影响图片标注信息
cedarkit-maps 架构需要继续重构,解决遗留问题,关注可配置性。
行动计划
构建以 cedarkit 工具栈为核心的通用绘图包
重构区域集合系统和全球集合系统绘图工具包
待定工作:在明确工具软件开发在 NWP 系列工作中的整体定位前不建议开展。详见“总结”章节中的简要讨论。
- STEP1:使用 reki 加载数据
- STEP2:使用 cedarkit-maps 绘制图片
- STEP3:完善现有的用户接口,处理命令行参数、配置文件、参数文件之间的关系
完善 cedarkit-maps 系列工具包
- 完成 cedarkit-maps 代码重构,向通用绘图包发展
- 继续开发 cedar-graph 库,提供定制能力
- 增强与 jupyter 笔记本的集成能力
- 推广工具库,发布笔记项目
相互作用
- 交互分析工具:作为 cedarkit 工具套件中的可视化组件,提供平面图绘制功能,支持 Jupyter 笔记本
工作流调度
现状
研发与业务运行试验的方式不统一
NWP 的模式研发试验与实时业务系统通常使用两套运行脚本:
- Shell。模式研发使用 Shell 脚本控制试验运行,总控脚本调用一系列任务 Shell 脚本。 少部分 NWP 系统使用 crontab + control script 的方式运行
- ecFlow。业务系统、ESMI 使用 ecFlow 控制试验运行。 ecFlow 根据预先定义任务依赖关系确定哪个任务该运行,并调用相应的任务脚本 (扩展的 Shell 脚本)
开发中的工作流调度工具
正在使用 Python 开发一款工作流调度工具 takler。
特点
- 仿照 ecFlow 软件架构实现,借鉴 ecFlow 的核心概念,方便对现有 ecFlow 系统进行改造
- 核心代码使用 Python 实现,工作流定义与工作流服务可以在同一个脚本中实现,可以模拟实现总控 Shell 脚本的一键式运行功能
- 使用协程支持并发操作,使用 gRPC 实现远程通讯
- 使用 Golang 开发客户端命令行程序 takler_client,类似 ecflow_client
动机
研发试验流程与业务系统流程不统一导致研发到业务转化成本过高
使用两套脚本的 NWP 系统在研发到业务的转化过程中需要将研发试验使用的 Shell 脚本转为 ecFlow 的运行系统。 这一步骤在当前的实践中由专门从事 ecFlow 业务系统建设的团队完成。 虽然业务系统建设团队也是业务系统的运维团队,但依然无法忽视维护两套运行体系带来的额外成本。 不光需要 Shell 到 ecFlow 的转化过程,在业务系统故障时也往往会要求判断 ecFlow 脚本是否和 Shell 保持一致,增加了排查故障的成本。 更详细介绍请参考《CEMC数值天气预报业务系统建设介绍(2023版)》。
ECMWF 在研发过程中虽然也使用 Shell 脚本进行测试,但研发部门和业务部门都通过 prepIFS 使用 ecFlow 进行系统整体测试 (e-suite 和 o-suite),这样就保证了研发与业务部门使用相同的流程进行开发,有助于降低 R2O 成本。 但在研发团队中推行 ecFlow 作为整体系统的单一运行方式尚在起步阶段,业务部门也正在尝试使用其他路线实现统一流程的目标。
当前正在尝试和未来拟尝试的方案如下:
- 方案1:使用 ecFlow 运行系统。ESMI 平台使用 ecFlow 运行模式试验,提供 Web 界面方便系统部署
- 方案2:保留完整的控制脚本(总控脚本、任务脚本、配置脚本),在 ecFlow 系统中调用相关脚本(配置脚本、任务脚本)。 全球模式和区域模式中已有相关工作。
- 方案3 (未开展):引入模板机制,动态生成 Shell 和 ecFlow 的运行脚本。(需先验证可行性)
需要在现有经验的基础上,为下一代 NWP 系统设计运行流程控制方案,同时支持研发试验和业务系统,维护一套运行脚本。
ecFlow 学习成本过高
ecFlow 系统需要编写工作流定义文件,运行调度依赖后台运行的 ecFlow 服务端进程 (ecflow_server
),上手成本较高,需要一定的学习时间。
ESMI 和 ECMWF IFSHub 均采用对 ecFlow 提供 Web 界面的方案,通过平台管理的 ecFlow 服务端进程来部署模式试验,将运行 ecFlow 系统的具体细节向用户隐藏,降低用户学习成本。
当前 NWP 系统的 ecFlow 流程由业务部门面向实时运行的业务系统开发,没有考虑模式研发试验的应用场景,较难推广到研发部门。
需要更轻量级的工作流解决方案,既能实现类似工作流调度工具对任务的精细控制,又能实现类似总控 Shell 脚本的一键式运行。
ecFlow 源代码过于复杂,较难针对当前需求实现二次开发
ecFlow 使用 C++ 实现,气象领域 C++ 相关编程人员比较少,基于 ecFlow 源代码进行二次开发成本较高。 CMA 曾经开展过相关工作,但笔者暂未发现相关成果的最终落地,从另一侧面说明使用 C++ 开发工作流调度软件不一定适合 CMA 的现状。 不过,随着下一代模式使用 C++ 开发的 C-Coupler,预计未来会有更多的气象领域专业人才可以从事 C++ 项目的开发工作,也许到时候可以重新考虑 NWP 支撑软件工具的布局。
建议当前最好使用 Python 开发,在未来考虑使用 GOLANG/C++ 等编译语言。
takler 项目距离实际应用还有较大差距
功能
- 稳定性。缺少错误处理,非常规使用路径的绝大部分情况可以导致整个程序的崩溃。 需要编写错误处理相关代码,减少程序崩溃次数,提高运行稳定性。
- 客户端。仅有命令行客户端,缺少可视化客户端 (UI),无法方便交互。 需要考虑采用何种方式开发一种可视化客户端:TUI、Web UI、Native UI。
- 安全。未考虑安全性,缺少身份验证等保护机制,无法应用在业务系统中。 ecFlow 提供一次性密钥、用户白名单、SSL 证书等安全机制。需要提供至少一种安全策略。
- 功能。与 ecFlow 相比尚缺少一些功能。对照 ecFlow 教程,实现基础功能。参照 NWP 系统维护实践,开发业务系统实际使用的功能。
- 日志。日志输出信息不够全面,无法提供有效的诊断信息。需要规范日志的输出格式,增加调试开关用于输出更多诊断信息。
实现
- 通讯依赖 gRPC 库,不利于部署。考虑将服务端的实现与接口分离,增加 gRPC 之外的服务端实现,比如使用 HTTP + JSON 实现通讯和序列化。
- 服务端与客户端通讯消息格式缺少扩展性,需要重新设计消息格式,支持通过中介代理转发消息。
- 远期目标:需要实现中介代理机制,实现跨超算平台的任务调度
管理
- 缺少单元测试,重构代码无法快速验证,只能手动跑一个复杂的测试用例。 需要为现有代码编写单元测试,并在未来开发过程中借鉴测试驱动开发 (TDD) 方法在新建代码同时开发测试代码。
- 仅有少量用户文档,没有及时更新。 需要参考 ecFlow 文档更新并补全教程章节,考虑编写更多用户文档。
资源
- 项目定位不明确,未投入足够的开发时间。是否属于单位未来发展方向?
行动计划
继续开发工作流调度工具takler
完善功能
- 参照 ecFlow,继续开发 NWP 业务流程使用到的功能
- 开发错误处理功能,增强运行稳定性,减少程序崩溃现象
- 优化日志输出信息,提供用于排错的信息
- 考虑设计权限管理机制,防止误操作
- 考虑开发 UI 界面
优化实现
- 重构服务端,将 gRPC 作为服务端的一个实现,考虑使用 HTTP 实现服务端
- 考虑使用其他方案实现服务端
- 重新设计通讯消息格式,支持消息转发
加强项目管理
- 编写单元测试
- 编写用户文档,参考 ecFlow 教程继续补全教程章节
争取资源
- 做好宣传,撰写专题文章,介绍 takler 技术实现细节
- 发布版本,尝试与其他平台集成,例如 ESMI
- 不忘初心,坚守本心,等待时机
针对下一代模式开发统一运行框架
研发业务系统统一运行流程框架技术,简化业务系统流程搭建工作,提高流程组件的复用率,降低维护成本。 该部分涉及专题 统一运行框架,不属于本文范围,不在本文中讨论。
相互作用
- 统一运行框架:统一运行框架使用工作流调度软件实现
- 系统集成:系统集成中的集成测试用例使用工作流调度软件实现
交互分析工具
现状
使用 HPC 分析数据
使用 GrADS、NCL、Python、Fortran 程序等进行交互分析或脚本批处理分析。
cedarkit 工具套件
特点
- 开发一系列工具,reki,cedarkit-comp,cedarkit-maps
- 开源发布
问题
- 功能太少
- 缺少文档
- 没有推广
- 持续开发力量不够
动机
缺少 Jupyter 交互分析环境
缺乏公用的 JupyterHub,只能在现有基础设施中手动运行 JupyterLab,比如在 HPC 登录节点运行。
与数据源的集成不好
当前数据分析任务通常只使用本地文件系统保存的数据,导致分析依赖的数据被大量保存在 HPC 共享文件系统中,尤其是预处理后的观测数据、ERA5 数据、NCEP GFS 数据等。
受 HPC 共享存储容量限制,长时间序列的业务数据保存在二级存储中。 二级存储上的数据只能通过 HPC 采用特定方式访问,需要通过命令行工具拷贝到 HPC 共享存储,或提交作业到特定队列后台分析,无法直接使用二级存储上的数据进行交互分析。
观测和业务数据也同样保存在 CMADaaS 平台中,但分析任务通常使用预先检索并保存到本地的数据文件,而不是在运行时从 CMADaaS 实时检索数据。 比如业务系统会在 HPC 共享文件系统归档预处理后的观测数据,业务检验系统保存观测、处理后的预报等数据。 数据目录往往会直接写入到数据分析任务的脚本中,一旦数据目录发生变动,会影响脚本的正常运行。
CMADaaS 数据和 GODAS 平台的数据均可以通过 Python 接口访问,但没有集成到 cedarkit 工具套件中。
建议将数据源与数据分析算法分离,通过一个单独的工具库来提供数据源功能,将算法开发人员从找数据的繁琐任务中解脱出来,让开发人员能更专注于算法开发。
行动计划
部署 JupyterHub 环境
探索在 HPC 上启动 JupyterLab 的方案,包括在不同类型的节点中运行 JupyterLab 实例:
- 登录节点
- 串行节点
- 并行节点
争取专用数据分析服务器资源,在 HPC 之外单独部署 JupyterHub 环境,与 ESMI 平台集成。
推进 cedarkit 项目
数据
- 支持更多数据源
- 使用标准数据结构(格点数据、观测表格数据)
计算
- 支持更多计算功能,参考 NCL、ESMValCore、earthkit-comp、geocat-comp 等项目
可视化
- 见可视化部分
相互作用
- 数据编解码:数据组件使用
- 观测资料检索:数据源组件使用
- 可视化:可视化组件
- 数据存储:数据源组件使用
数据存储
注:本章节非笔者当前关注领域,仅简略介绍
格点数据存储
现状
数据平台
特点
- 利用现有归档数据存储,保存索引信息
- 并发抽取,支持数据计算
- 提供用户网站和命令行工具
关注点
- 获取 GRIB2 数据的元信息依赖 ecCodes,缺少对 CEMC 定制要素的支持。 需要与数据编解码库相关联
- 索引库受当前平台的基础设施存储容量限制。需要对现有基础设施进行扩容
- 索引数据源来自老二级存储和 CMADaaS ,均支持 Linux 挂载,但新二级存储无法直接挂载。 需要和相关部门合作寻找合适的解决方案
- 缺少完整功能的 Python 编程接口,仅有临时实现。 需要为数据平台开发一个数据源工具库,提供其他工具库使用
参考文献
[1] 贾晓振,胡江凯,王大鹏,梁晨.长时间序列格点数据管理平台的设计与实践[J].气象科技,2024,52(6):797~806
动机
数据平台如何与模式系统对接
- 尝试开发 HPC 上面向实时系统的索引库,类似 ECMWF 的 FDB 库
行动计划
制定数据元信息规范
- 用于数据检索语法
- key / value 格式
- 类似 MARS 关键字
继续发展模式数据平台
探索建立 FDB 库的可行性
方案:
- 近期:MODEL -> POST -> FDB -> PICTURE
- 远期:MODEL -> FDB -> PRODUCT
相互作用
- 数据编解码库:使用解码库解析格点数据,生成数据元信息
- 可视化工具:作为格点数据来源
观测数据存储
现状
- 没有统一的观测数据存储
- 不同项目使用不同的方式(文件、数据库等)
- 业务系统将处理后的观测资料保存成文件,使用特定账户保存
动机
多系统间观测资料能否共享
当前已有部分观测资料实现系统间的共享:
- 区域台风模式使用区域模式的云分析资料
- 区域集合模式使用区域模式的常规观测、雷达、卫星等资料
行动计划
- 探索统一观测资料检索系统的可行性
- 如何支持其他项目的观测数据存储需求
相互作用
- 数据编解码库:解析观测资料
观测资料预处理
注:当前未涉及,暂时略过。
数据分发
注:当前未涉及,暂时略过。
后处理
注:当前未涉及,暂时略过。
总结
本文介绍了笔者个人对数值天气预报业务系统支撑软件工具发展方向的一些想法。 因为个人思考的局限性,不同方向的介绍有详有略,没有形成一个完整的技术发展规划。
NWP 系统支撑软件工具还有几个问题需要进一步讨论:
- 开源 vs 自研。软件开发和维护需要投入大量的人力资源成本。在开启一个新项目之前,首先要回答一个问题:为什么要做这个项目。 现有的解决方案存在哪些问题,是否可以直接引入开源项目解决当前问题,自研软件是否有可信的证据能带来足够的收益并能负担未来的维护成本。 自研软件也要积极加入到开源社区中,争取借助社区的力量来分担维护成本。
- 工具软件开发的地位问题。NWP 系统开发单位通常以系统或平台作为主要的考核指标,工具软件仅是某项工作任务的附属产物,而很少作为一个正式的工作任务,过往经验很难说服开发人员投入到工作软件开发中。 需要解决工具软件开发在整个 NWP 系统工作中的定位问题,寻找合适方式认定开发工具软件的贡献,鼓励团队开展相关工作。
- 团队开发。在解决软件开发地位问题后,需要探索团队开发的合适途径,尽量避免单人开发的项目,让更多同事参与到工具软件的开发过程中,也能让工具软件得到更多的应用。
随着相关工作的推进和内部讨论的思维碰撞,可能会有新的理解,本文介绍的内容可能不再适用。 不过,永远没有完美的方案,本文可以作为阶段性想法的记录,为未来工作提供一些参考。 笔者将继续开展数值天气预报业务系统支撑软件工具的相关工作,并持续发表相关博文。
参考
相关博文