当使用 NFSv4 时,我的客户报告他们的 MPI 程序有时会报告文件无法打开或找不到文件的错误。
我编写了一个示例 MPI-IO 程序,并确认如果计算节点上的 MPI 进程尝试访问从 NFS 共享的同一个文件,该程序将失败。经过多次检查,结果发现将 NFS 挂载从 v4.1 更改为 v3 可以消除此问题。
我仍然想使用 NFSv4,因为它安全并且可能提高速度。所以我想知道我应该添加哪些参数才能使其工作。
操作系统:CentOS 7.6 更新至最新版本,nfs-utils 1.3.0,内核 3.10.0-957.12.2
服务器导出:
/home 10.0.214.0/24(rw,no_subtree_check,no_root_squash)
客户端 fstab:
ib-orion-io1:/home /home nfs defaults,rdma,port=20049,nodev,nosuid 0 2
NFSv4 客户端挂载:
ib-orion-io1:/home on /home type nfs4 (rw,nosuid,nodev,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=rdma,port=20049,timeo=600,retrans=2,sec=sys,clientaddr=10.0.214.11,local_lock=none,addr=10.0.214.5)
NFSv3 客户端挂载
ib-orion-io1:/home on /home type nfs (rw,nosuid,nodev,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=rdma,port=20049,timeo=600,retrans=2,sec=sys,mountaddr=10.0.214.5,mountvers=3,mountproto=tcp,local_lock=none,addr=10.0.214.5)
NFSv4 客户端上显示错误
Testing simple MPIO program with 112 processes accessing file tttestfile
(Filename can be specified via program argument)
Proc 0: hostname=node001
Proc 0: MPI_File_open failed (Other I/O error , error stack:
ADIO_OPEN(219): open failed on a remote node)
Proc 66: MPI_File_open failed (File does not exist, error stack:
ADIOI_UFS_OPEN(39): File tttestfile does not exist)
Proc 1: MPI_File_open failed (Other I/O error , error stack:
ADIO_OPEN(219): open failed on a remote node)
Proc 84: MPI_File_open failed (File does not exist, error stack:
ADIOI_UFS_OPEN(39): File tttestfile does not exist)
示例并行 MPI 文件 IO 程序取自 HDF5。
参见“==>Sample_mpio.c<==" 段落 https://support.hdfgroup.org/ftp/HDF5/current/src/unpacked/release_docs/INSTALL_parallel
答案1
我发现这是因为 NFSv4 默认为“ac”。因此,当 MPI 中的等级 0 创建文件时,其他进程在几毫秒后开始打开它。NFS 客户端返回缓存信息,然后出现“文件未找到”的情况。
当添加“noac”选项时,一切又变得顺利了。
编辑:写入仍然有错误。我稍后会尝试使用 NFSv3。示例代码:
#include <mpi.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char hostname[16];
char readhost[16];
int mpi_size, mpi_rank;
MPI_File fh;
char *filename = "./mpirw.data";
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
gethostname(hostname, 16);
if (mpi_rank == 0)
{
MPI_File_open(MPI_COMM_SELF, filename,
MPI_MODE_CREATE | MPI_MODE_RDWR, MPI_INFO_NULL, &fh);
printf("%d@%s created file\n", mpi_rank, hostname);
MPI_File_close(&fh);
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_File_open(MPI_COMM_WORLD, filename,
MPI_MODE_RDWR, MPI_INFO_NULL, &fh);
printf("%d@%s opened file\n", mpi_rank, hostname);
MPI_Status status;
int count = strlen(hostname);
MPI_File_write_at(fh, mpi_rank * 16,
hostname, count + 1, MPI_CHAR, &status);
printf("%d@%s wrote OK\n", mpi_rank, hostname);
MPI_Barrier(MPI_COMM_WORLD);
if (mpi_rank == 0)
MPI_File_write_at(fh, mpi_size * 16, "\n", 1, MPI_CHAR, &status);
MPI_File_read_at(fh, mpi_rank * 16,
readhost, count + 1, MPI_CHAR, &status);
if (strcmp(hostname, readhost) != 0)
printf("%d@%s read ERROR, got %s\n", mpi_rank, hostname, readhost);
else
printf("%d@%s read OK, got %s\n", mpi_rank, hostname, readhost);
MPI_File_close(&fh);
}
尽管程序可能会报告“read OK”,但是 hexdump 输出显示输出被截断。