我正在运行一个具有数千个MPI进程的模拟,并且需要将输出数据写入一小组文件。例如,尽管我可能有10000个进程,但我只想写出10个文件,每个文件都有1000个写入文件(在适当的偏移量下)。正确的方法是为将要写入相同文件的进程组创建一个新的通信器,使用MPI_File_open()为该通信器打开一个共享文件,然后使用MPI_File_write_at_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();
}我可以用mpicc file.c -lm编译,比如用mpirun -np 20 a.out运行20个进程,并得到预期的输出(四个文件,每个文件有五个条目),但我不确定这是否是技术上正确/最优的方法。有什么不一样的地方吗?
发布于 2017-03-04 04:48:59
你的方法是正确的。为了澄清,我们需要重新审视标准和定义。来自MPI_File_Open MPI:消息传递接口标准版本2.2的API (第391页)
int MPI_File_open(MPI_Comm comm,char *filename,int amode,MPI_Info info,MPI_File *fh)
描述:
MPI_FILE_OPEN在comm通信器组中的所有进程上打开由文件名文件名标识的文件。MPI_FILE_OPEN是一个集体例程:所有进程必须为amode提供相同的值,所有进程都必须提供引用相同文件的文件名。(信息的值可能有所不同。)通信必须是intracommunicator;,将intercommunicator传递给MPI_FILE_OPEN是错误的。
内部通信者与相互通信者(第134页):
为了本章的目的,只需知道有两种类型的传播者:内部传播者和相互传播者。内部通信程序可以被看作是与上下文关联的单个进程组的标识符。互连器标识与上下文关联的两组不同的进程。
将内部intracommunicator传递给MPI_File_open()的目的是指定一组将对文件执行操作的进程。MPI运行时需要这些信息,因此当集体I/O操作发生时,它可以强制执行适当的同步。程序员有责任理解应用程序的逻辑,并创建/选择正确的内部通信程序。
一个功能强大的API中的MPI_Comm_Split(),它允许将一个通信组分成不相交的子组,用于不同的用例,包括MPI /O。
发布于 2017-02-24 22:04:04
MPI_File_write_at_all应该是实现这一目标的最有效方法。对于大型、非连续的并行写入共享文件,集体IO函数通常是最快的,而_all变体将查找和写入合并到一个调用中。
发布于 2017-03-09 18:16:46
我认为这可能是上面的一个错误,但表示集体操作的是"_all“。
但是,我想指出的主要一点是,集体操作速度更快的原因是它们使I/O系统能够从许多进程聚合数据。您可能会从1000个进程发出1000次写入,但是使用集合形式,可以将其聚合为对文件的单个大写入(而不是1000次小写入)。当然,这是最好的情况,但对于我所见过的共享文件的访问,集体I/O的速度是非集体的1000倍,当然,对于比这更复杂的IO模式,这种改进可能是戏剧性的。
https://stackoverflow.com/questions/42431064
复制相似问题