C 使用MPI-IO写入多个共享文件

C 使用MPI-IO写入多个共享文件,c,mpi,hpc,mpi-io,C,Mpi,Hpc,Mpi Io,我正在运行一个包含数千个MPI进程的模拟,需要将输出数据写入一小部分文件。例如,尽管我可能有10000个进程,但我只想写出10个文件,每个文件上写1000个文件(以适当的偏移量)。这样做的正确方法是为将要写入相同文件的进程组创建一个新的通信器,使用MPI\u file\u open()打开该通信器的共享文件,然后使用MPI\u file\u write\u all()对其进行写入。对吗?以下代码是我编写的一个玩具示例: #include <mpi.h> #include <ma

我正在运行一个包含数千个MPI进程的模拟,需要将输出数据写入一小部分文件。例如,尽管我可能有10000个进程,但我只想写出10个文件,每个文件上写1000个文件(以适当的偏移量)。这样做的正确方法是为将要写入相同文件的进程组创建一个新的通信器,使用
MPI\u file\u open()
打开该通信器的共享文件,然后使用
MPI\u file\u write\u all()
对其进行写入。对吗?以下代码是我编写的一个玩具示例:

#include <mpi.h>
#include <math.h>
#include <stdio.h>

const int MAX_NUM_FILES = 4;

int main(){
    MPI_Init(NULL, NULL);

    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int numProcs;
    MPI_Comm_size(MPI_COMM_WORLD, &numProcs);

    int numProcsPerFile = ceil(((double) numProcs) / MAX_NUM_FILES);
    int targetFile = rank / numProcsPerFile;

    MPI_Comm fileComm;
    MPI_Comm_split(MPI_COMM_WORLD, targetFile, rank, &fileComm);

    int targetFileRank;
    MPI_Comm_rank(fileComm, &targetFileRank);

    char filename[20]; // Sufficient for testing purposes
    snprintf(filename, 20, "out_%d.dat", targetFile);
    printf(
        "Proc %d: writing to file %s with rank %d\n", rank, filename,
        targetFileRank);

    MPI_File outFile;
    MPI_File_open(
        fileComm, filename, MPI_MODE_CREATE | MPI_MODE_WRONLY,
        MPI_INFO_NULL, &outFile);

    char bufToWrite[4];
    snprintf(bufToWrite, 4, "%3d", rank);

    MPI_File_write_at_all(
        outFile, targetFileRank * 3,
        bufToWrite, 3, MPI_CHAR, MPI_STATUS_IGNORE);

    MPI_File_close(&outFile);
    MPI_Finalize();
}
#包括
#包括
#包括
const int MAX_NUM_FILES=4;
int main(){
MPI_Init(NULL,NULL);
整数秩;
MPI通信等级(MPI通信世界和等级);
国际货币基金组织;
MPI通信大小(MPI通信世界和numProcs);
int numProcsPerFile=ceil((双)numProcs)/MAX_NUM_文件);
int targetFile=rank/numProcsPerFile;
MPI_通信文件通信;
MPI_通信分割(MPI_通信世界、目标文件、等级和文件通信);
int targetFileRank;
MPI通信等级(fileComm和targetFileRank);
char filename[20];//足以用于测试目的
snprintf(文件名,20,“out_u%d.dat”,targetFile);
printf(
“进程%d:写入文件%s,秩为%d\n”,秩,文件名,
targetFileRank);
MPI_文件输出文件;
MPI\u文件\u打开(
fileComm,filename,MPI_MODE_创建|仅限MPI_MODE_wr,
MPI_信息_NULL和输出文件);
碳硼镁石[4];
snprintf(bufToWrite,4,“%3d”,排名);
MPI\u文件\u写入\u(
outFile,targetFileRank*3,
bufToWrite,3,MPI_字符,MPI_状态(忽略);
MPI文件关闭(&OUT文件);
MPI_Finalize();
}

我可以使用
mpicc file.c-lm
进行编译,并使用
mpirun-np 20 a.out
运行20个进程,然后得到预期的输出(四个文件,每个文件有五个条目),但我不确定这是否是技术上正确/最佳的方法。有什么我应该做的不同吗?

MPI文件写入应该是最有效的方法。对于对共享文件的大型非连续并行写入,集合IO函数通常最快,而“全部”变量将查找和写入合并到一个调用中。

MPI文件“全部写入”应该是最有效的方法。对于对共享文件的大型非连续并行写入,集合IO函数通常最快,而_all变量将查找和写入合并到一个调用中。

您的方法是正确的。为了澄清,我们需要重新审视标准和定义。MPI\u文件\u打开API自(第391页)

int MPI_文件\u打开(MPI_通信,字符*文件名,int amode,MPI_信息, MPI_文件*fh)

说明:

MPI_FILE_OPEN在中的所有进程上打开由文件名标识的文件 通信通信组。MPI_FILE_OPEN是一个集合例程:所有进程都必须 为amode提供相同的值,所有进程都必须提供引用的文件名 相同的文件。(信息的值可能会有所不同。)通信必须是一个内部通信者;它是 将内部通讯器传递到MPI\u文件\u打开时出错

内部通信者与内部通信者(第134页):

就本章而言,只要知道有两种类型就足够了 通讯器的类型:内部通讯器和内部通讯器。内部沟通者 可以将其视为与上下文链接的单个进程组的标识符。一 intercommunicator标识与上下文链接的两组不同的进程

将内部通信程序传递给
MPI\u File\u open()
的目的是指定一组将对文件执行操作的进程。MPI运行时需要此信息,因此它可以在发生集体I/O操作时强制执行适当的同步。程序员有责任理解应用程序的逻辑并创建/选择正确的内部通讯器


MPI\u Comm\u Split()
在一个强大的API中,允许将通信组拆分为不相交的子组,以用于不同的用例,包括MPI I/O。您的方法是正确的。为了澄清,我们需要重新审视标准和定义。MPI\u文件\u打开API自(第391页)

int MPI_文件\u打开(MPI_通信,字符*文件名,int amode,MPI_信息, MPI_文件*fh)

说明:

MPI_FILE_OPEN在中的所有进程上打开由文件名标识的文件 通信通信组。MPI_FILE_OPEN是一个集合例程:所有进程都必须 为amode提供相同的值,所有进程都必须提供引用的文件名 相同的文件。(信息的值可能会有所不同。)通信必须是一个内部通信者;它是 将内部通讯器传递到MPI\u文件\u打开时出错

内部通信者与内部通信者(第134页):

就本章而言,只要知道有两种类型就足够了 通讯器的类型:内部通讯器和内部通讯器。内部沟通者 可以将其视为与上下文链接的单个进程组的标识符。一 intercommunicator标识与上下文链接的两组不同的进程

将内部通信程序传递给
MPI\u File\u open()
的目的是指定一组将对文件执行操作的进程。MPI运行时需要此信息,因此它可以在发生集体I/O操作时强制执行适当的同步。程序员有责任理解应用程序的逻辑并创建/选择正确的内部通讯器

MPI\u Comm\u Split()
在一个强大的API中,允许将通信组拆分为不相交的子组,以用于不同的用例,包括MPI I/O。