并行 NetCDF 操作

2022/10/14 IO

利用 NetCDF4 自带的 api 完成并行读写的 Demo

NetCDF-4 文件的并行 I/O 通过 HDF5 库实现,而对经典文件的并行 I/O 通过 PnetCDF 实现。 编译 netCDF-4 时需要开启并行功能才能支持并行功能。

nc_open_par() (opens new window)nc_create_par() (opens new window) 函数用于创建/打开具有并行访问权限的 netCDF 文件。

定义一个错误处理的宏

static int _nc_err;
#define NCERR(ncfunc, str)                     \
	_nc_err = ncfunc;                            \
	if (_nc_err != NC_NOERR)                     \
	{                                            \
		std::cout << nc_strerror(_nc_err) << std::endl;  \
		throw std::runtime_error("error " + std::string(str) + ", error code: " + std::to_string(_nc_err));                      \
	}
1
2
3
4
5
6
7
8

头文件除了需要包括 netcdf.h 以外还需要包括 netcdf_par.h

创建文件需要

NCERR(nc_create_par(file_name.c_str(), NC_NETCDF4, comm, info, &ncid), "create parallel file.");
1

打开文件时需要使用 nc_open_par 而非 nc_open

NCERR(nc_open_par(file_name.c_str(), NC_WRITE, comm, info, &ncid), "Open parallel file.");
1

其中需要注意的是:这两个函数需要 MPI 的相关类型,即

MPI_Comm comm = MPI_COMM_WORLD;
MPI_Info info = MPI_INFO_NULL;
1
2

注意

与这些函数关联的并行访问不是数据文件的特征,而是其打开方式。

定义数据、写入数据、关闭文件与正常调用(non-MPI)相同

NCERR(nc_def_dim(ncid, "level", var_size, &dimid), "create dim.");
NCERR(nc_def_var(ncid, "test", NC_DOUBLE, ndims, &dimid, &varid), "create var.");
NCERR(nc_put_vara_double(ncid, varid, &start, &count, data.get()), "Write data.");
NCERR(nc_close(ncid), "close file.");
1
2
3
4

值得注意的是可通过 nc_var_par_access 切换独立与集合模式

NCERR(nc_var_par_access(ncid, varid, NC_COLLECTIVE), "change to NC_COLLECTIVE");
// or
NCERR(nc_var_par_access(ncid, varid, NC_INDEPENDENT), "change to NC_INDEPENDENT");
1
2
3

集合和独立模式的区别有:

集合模式下,所有进程都必须参与,而是独立模式,任何进程都可以访问数据而无需等待其他进程。 所有 netCDF 元数据写入操作都是集合的。即:组、类型、变量、维度或属性的创建和定义。 数据读取和写入(nc_put_*nc_get_* 调用可以是独立模式(默认)或集合模式。

Last Updated: 2023-10-29T08:26:04.000Z