不同打包方式下GRIB2文件加载速度对比:简单打包与JPEG压缩
GRIB 2 格式文件支持使用不同方式保存要素场数据,可以使用二维数组的一维展开,也可以使用类似 JPEG、PNG 等图片格式对二维数据进行压缩。
本文介绍不同打包方式下从 GRIB 2 文件中加载要素场的速度。
打包方式
不同中心生成的 GRIB 2 数据使用不同的打包方式:
- CMA 天气预报模式:JPEG2000 压缩 (grid_jpeg)
- ECMWF 公开数据:简单打包,无压缩 (grid_simple)
- NCEP GFS:复杂打包 (grid_complex_spatial_differencing)
本文测试 wgrib2 支持的部分打包方式,如下表所示:
wgrib2 name | eccodes packingType | 说明 |
---|---|---|
jpeg | grid_jpeg | JPEG2000 压缩 |
simple | grid_simple | 无压缩,打包缩放后的整数 |
ieee | grid_ieee | IEEE 格式 (每个数据点 4 字节) |
complex1 | grid_complex | complex packing |
complex2 | grid_complex_spatial_differencing | complex packing, pack increments (deltas) |
complex3 | grid_complex_spatial_differencing | complex packing, pack increments after linear extrapolation |
aec | grid_ccsds | 使用 libaec 实现的 CCSDS 压缩 |
准备数据
使用 CMA-MESO V5.1 的等压面产品作为测试数据,原始文件使用 JPEG 方式压缩。
使用 wgrib2 -set_grib_type
命令将 GRIB 2 文件转为不同的打包方式,例如下面命令将文件转为 simple 打包方式:
wgrib2 -set_grib_type simple rmf.hgra.2022031000003.grb2 -grib_out rmf.hgra.2022031000003.grb2.simple
转换后的文件列表如下:
1.1G rmf.hgra.2022031000003.grb2
1.3G rmf.hgra.2022031000003.grb2.aec
1.6G rmf.hgra.2022031000003.grb2.complex1
1.3G rmf.hgra.2022031000003.grb2.complex2
1.3G rmf.hgra.2022031000003.grb2.complex3
8.7G rmf.hgra.2022031000003.grb2.ieee
3.6G rmf.hgra.2022031000003.grb2.simple
测试
读取代码
从 GRIB 2 文件中加载层次类型为 isobaricInhPa
的所有温度场,使用两种方式:
import cfgrib
file_path = "./rmf.hgra.2022031000003.grb2"
ds = cfgrib.open_dataset(
file_path,
backend_kwargs={
'filter_by_keys': {'typeOfLevel': 'isobaricInhPa', 'shortName': 't'},
'indexpath': ''
}
)
ds.load()
file_path = "./rmf.hgra.2022031000003.grb2"
ds = load_field_from_file(
file_path,
parameter="t",
level_type="isobaricInhPa",
level="all"
)
ds.load()
注:cfgrib 的
open_dataset()
函数使用延迟加载方式,仅读取 GRIB2 消息头,不读取数据值,测试代码使用ds.load()
载入数据值。 reki 的load_field_from_file()
会一次性解码消息头和数据值,ds.load()
语句可以注释掉。
测试方法
在 CMA-PI HPC 上使用简单方法测试以上程序的运行时长,为了避免 import 阶段时长带来的差异,直接统计核心段的墙钟时间。 统计结果仅是 近似值,只用来对比不同打包方式的相对运行时长。
注意:以下方法得到的运行时长仅是部分代码运行的墙钟时间,不是该段代码运行的实际时间,也不是整个程序运行的时间。
import pandas as pd
start_time = pd.Timestamp.now()
# ... real code ...
end_time = pd.Timestamp.now()
print(end_time - start_time)
测试结果
不同打包方式下 cfgrib 和 reki 版本的载入时间如下:
打包方式 | cfgrib (s) | reki (s) |
---|---|---|
jpeg | 27 | 22 |
simple | 5 | 3 |
ieee | 13 | 9 |
aec | 5 | 3 |
complex1 | 5 | 3 |
complex2 | 5 | 3 |
complex3 | 5 | 3 |
简单打包方式比 JPEG 压缩方式加载速度快 5 倍以上。
进一步分析
不同文件仅打包方式不同,而打包方式与要素场数据值解码操作有关。
也就是上述代码运行时长与 eccodes.grib_get_double_array()
函数执行时间有关。
为了验证这一想法,对函数调用的运行时长进行进一步测试分析。
使用 Profile 工具分析代码运行时长,main()
函数和 ggrib_get_double_array()
函数运行总时长如下表所示,单位是毫秒 (ms):
打包方式 | main | get array |
---|---|---|
simple | 4254 | 368 |
jpeg | 22706 | 20805 |
ieee | 9873 | 337 |
aec | 3916 | 1644 |
complex1 | 3740 | 1101 |
complex2 | 4108 | 968 |
complex3 | 3382 | 1024 |
main()
函数中其他部分运行时长与 grib_get_double_array()
函数运行时长的关系如下图所示:
图 不同打包方式下核心段代码的运行时长
从上图可以看到,JPEG 压缩方式主要耗时都在数组解码,也就是 JPEG2000 解压缩操作。 简单打包方式与 JPEG 压缩方式运行时长的差异也基本来自于数组解码操作。
参考
reki 库是为 CMA 天气模式开发的数据准备 Python 开源工具库,提供检索要素场的便捷方法。
项目地址:https://github.com/nwpc-oper/reki
文档:https://reki.readthedocs.io/
相关文章:
一篇对比文件大小的微信公众号文章:《一份GRIB与NetCDF的文件体积对比报告》