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

Writing to multiple shared files with MPI-IO

我正在 运行 对数千个 MPI 进程进行模拟,需要将输出数据写入一小组文件。例如,尽管我可能有 10,000 个进程,但我只想写出 10 个文件,每个文件写入 1,000 个(以某个适当的偏移量)。 AFAIK 执行此操作的正确方法是为将写入相同文件的进程组创建一个新的通信器,使用 MPI_File_open() 为该通信器打开一个共享文件,然后使用 [=12] 写入它=].那是对的吗?以下代码是我编写的玩具示例:

#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();
}

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

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

你的做法是正确的。为了澄清,我们需要重新审视标准和定义。 MPI_File_Open API 来自 MPI: A Message-Passing Interface Standard Version 2.2(第 391 页)

int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh)

描述:

MPI_FILE_OPEN opens the file identified by the file name filename on all processes in the comm communicator group. MPI_FILE_OPEN is a collective routine: all processes must provide the same value for amode, and all processes must provide filenames that reference the same file. (Values for info may vary.) comm must be an intracommunicator; it is erroneous to pass an intercommunicator to MPI_FILE_OPEN.

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

For the purposes of this chapter, it is sufficient to know that there are two types of communicators: intra-communicators and inter-communicators. An intracommunicator can be thought of as an identifier for a single group of processes linked with a context. An intercommunicator identifies two distinct groups of processes linked with a context.

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

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

我觉得可能是上面的错别字,不过是“_all”表示的是集体行动

然而,我想表达的主要观点是,集体操作更快的原因是它们使 I/O 系统能够聚合来自许多进程的数据。您可以从 1000 个进程发出 1000 次写入,但使用集体形式,这可能会聚合到对文件的单个大写入(而不是 1000 次小写入)。这当然是最好的情况,但改进可能是巨大的——对于共享文件的访问,我看到集体 I/O 比非集体快 1000 倍,诚然对于比这更复杂的 IO 模式。