TLDR
当我并行创建文件时,循环挂起。为什么? (参见下面的代码)另外,写入多个二进制文件(由迭代变量确定的指针和偏移量)的安全/有效方法是什么?
背景和问题:
我希望我的代码可以执行以下操作:
(1)所有进程读取包含双精度矩阵的单个二进制文件 - >已经使用MPI_File_read_at()
实现了这一点(2)对于输入数据的每个“列”,使用每个“行”中的数字执行计算,并将每列的数据保存到其自己的二进制输出文件中(“File0.bin” - >第0列)
(3)为了使用户能够指定任意数量的进程,我使用简单的索引将矩阵视为一个长(行)X(cols)向量,并按进程数分割该向量。每个进程获取(行)X(cols)/ tot_proc条目来处理......使用这种方法,列不会被每个进程整齐划分,因此,每个进程都需要访问与其对应的任何文件和,使用适当的偏移量,写入正确文件的正确部分。目前,生成的文件将被分段并不重要。
当我朝着这个目标努力时,我编写了一个简短的程序来在循环中创建二进制文件,但循环在最后一次迭代时挂起(13个文件分为4个进程)。要创建的文件数=(行)。
问题1 为什么这段代码会在循环结束时挂起?在我的4个进程的玩具示例中,id_proc 1-3有3个要创建的文件,而id_proc 0(根进程)有4个要创建的文件。当根进程尝试使其成为第4个文件时,循环挂起。注意:我正在使用mpic ++在运行Ubuntu的笔记本电脑上编译它。
问题2 最后我会添加第二个for循环,就像你在下面看到的一样,除了在这个循环中,进程必须写入已经创建的二进制文件的相应部分。我计划使用MPI_File_write_at()来执行此操作,但我还读过使用MPI_File_set_size()来静态调整文件大小,然后,每个进程都应该使用MPI_File_set_view()来拥有自己的文件视图。所以,我的问题是,为了实现这一点,我应该做以下几点吗?
(循环1)MPI_File_open(...,MPI_WRONLY | MPI_CREATE,...),MPI_File_set_size(),MPI_File_close()
(循环2)MPI_File_open(...,MPI_WRONLY,...),MPI_File_set_view(),MPI_File_write_at(),MPI_File_close()
....循环2似乎会因每次迭代打开和关闭文件而变慢,但我事先并不知道用户将提供多少输入数据,也不知道用户将提供多少进程。例如,进程N可能需要写入文件1的末尾,文件2的中间和文件8的结尾。原则上,所有这些都可以通过偏移来处理。我不知道的是MPI是否允许这种灵活性。
代码尝试并行创建多个文件:
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <vector>
#include <fstream>
#include <string>
#include <sstream>
#include <cmath>
#include <sys/types.h>
#include <sys/stat.h>
#include <mpi.h>
using namespace std;
int main(int argc, char** argv)
{
//Variable declarations
string oname;
stringstream temp;
int rows = 13, cols = 7, sz_dbl = sizeof(double);
//each binary file will eventually have 7*sz_dbl bytes
int id_proc, tot_proc, loop_min, loop_max;
vector<double> output(rows*cols,1.0);//data to write
//MPI routines
MPI_Init(&argc,&argv);//initialize MPI
MPI_Comm_rank(MPI_COMM_WORLD,&id_proc);//get "this" node's id#/rank
MPI_Comm_size(MPI_COMM_WORLD,&tot_proc);//get the number of processors
//MPI loop variable assignments
loop_min = id_proc*rows/tot_proc + min(rows % tot_proc, id_proc);
loop_max = loop_min + rows/tot_proc + (rows % tot_proc > id_proc);
//File handle
MPI_File outfile;
//Create binary files in parallel
for(int i = loop_min; i < loop_max; i++)
{
temp << i;
oname = "Myout" + temp.str() + ".bin";
MPI_File_open(MPI_COMM_WORLD, oname.c_str(), MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &outfile);
temp.clear();
temp.str(string());
MPI_File_close(&outfile);
}
MPI_Barrier(MPI_COMM_WORLD);//with or without this, same error
MPI_Finalize();//MPI - end mpi run
return 0;
}
到目前为止我读过的教程/信息页面:
http://beige.ucs.indiana.edu/B673/node180.html
http://beige.ucs.indiana.edu/B673/node181.html
http://mpi-forum.org/docs/mpi-2.2/mpi22-report/node305.htm
https://www.open-mpi.org/doc/v1.4/man3/MPI_File_open.3.php
http://www.mcs.anl.gov/research/projects/mpi/mpi-standard/mpi-report-2.0/node215.htm
答案 0 :(得分:1)
MPI_File_open()
是一项集体操作,这意味着MPI_COMM_WORLD
的所有任务都必须在相同时打开相同的文件。
如果您想为每个任务打开一个进程,请改用MPI_COMM_SELF
。