【问题标题】:MPI Binary File I/O Basic Function and Performance QuestionsMPI 二进制文件 I/O 基本功能和性能问题
【发布时间】:2017-06-26 19:06:49
【问题描述】:

TLDR

当我并行创建文件时,For 循环挂起。为什么? (见下面的代码)另外,写入多个二进制文件(指针和偏移量由迭代变量确定)的安全/有效方法是什么?

背景和问题

我希望我的代码执行以下操作:

(1) 所有进程都读取一个包含双精度矩阵的单个二进制文件 -> 已经使用 MPI_File_read_at() 实现了这一点

(2) 对于输入数据的每一“列”,使用每一“行”中的数字进行计算,并将每一列的数据保存到其自己的二进制输出文件中(“File0.bin” -> 列 0)

(3) 为了使用户能够指定任意数量的进程,我使用简单的索引将矩阵视为一个长 (rows)X(cols) 向量,并按进程数拆分该向量。每个进程获取 (rows)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

Parallel output using MPI IO to a single file

Is it possible to write with several processors in the same file, at the end of the file, in an ordonated way?

【问题讨论】:

  • 最简单的方法是使用进程 id 0 作为主进程并通过它提供所有 IO。这不会扩展到大规模并行化,但您可能只有几个处理器。
  • @MalcolmMcLean 感谢您的评论。就我而言,我确实可以使用数千个处理器,所以我希望我能够大规模扩展。

标签: c++ for-loop mpi


【解决方案1】:

MPI_File_open() 是一个集体操作,这意味着来自MPI_COMM_WORLD 的所有任务必须在同一时间打开相同文件。

如果您想为每个任务打开一个进程,请改用MPI_COMM_SELF

【讨论】:

  • 感谢您的回复。这修复了我显示的代码中的错误。顺便问一下,你有问题 2 的 cmet 吗?
猜你喜欢
  • 2013-02-05
  • 2020-08-11
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
相关资源
最近更新 更多