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