在c++和MPI中独立并行写入文件

independent parallel writing into files in C++ and MPI

本文关键字:并行 文件 独立 c++ MPI      更新时间:2023-10-16

我已经在c++和MPI中实现了一个代码,该代码应该在大约7个文件中为每个CPU处理其数据进行数百万次计算并保存数百万个数字。我使用了大约1万个核心,总共有7万个文件,其中有数百万行代码需要并行编写。

我使用ofstream进行写入,但由于某种原因,MPI代码在中间中断,文件似乎是空的。我希望每个处理器独立地编写其7个文件,而不是所有其他处理器,根据我的搜索,这可以使用MPI完成,但我在许多资源中读到它,我无法理解它如何用于独立编写,并在执行期间动态指定文件名。如果是正确的,谁能尽可能详细地解释一下吗?如果没有,请尽可能详细地解释你的其他建议。

我现在写的东西是这样的:

if (rank == 0)
    {
    if(mkdir("Database",0777)==-1)//creating a directory
    {
    }
    rowsCount = fillCombinations(BCombinations,  RCombinations,
                                 BList,               RList,
                                 maxCombinations,        BIndexBegin, 
                                 BIndexEnd,           RIndexBegin, 
                                 RIndexEnd,    
                                 BCombinationsIndex,  RCombinationsIndex
                          );
}
//then broad cast all the arrays that will be used in all of the computations and at the root 
//send all the indexes to work on on the slaves then at the slave 
or (int cc = BeginIndex ; cc <= EndIndex; cc++)
        {

           // begin by specifying the values that will be used 
           // and making files for each B and R in the list

            BIndex      = betaCombinationsIndex   [cc];
            RIndex     = roughCombinationsIndex  [cc];

            //creating files to save data in and indicating the R and B by their index 
            //specifying files names
           std::string str1;
           std::ostringstream buffer1;
           buffer1 << "Database/";
           str1 = buffer1.str();
           //specifying file names
            std::ostringstream pFileName;
            std::string ppstr2;
            std::ostringstream ppbuffer2;
            ppbuffer2 <<"P_"<<"Beta_"<<(BIndex+1)<<"_Rho_"<<(RIndex+1)<<"_sampledP"<< ".txt";
            ppstr2 = ppbuffer2.str();
            pFileName <<str1.c_str()<<ppstr2.c_str();
            std::string p_file_name = pFileName.str();
            std::ostringstream eFileName;
            std::string eestr2;
            std::ostringstream eebuffer2;
            eebuffer2 <<"E_"<<"Beta_"<<(BIndex+1)<<"_Rho_"<<(RIndex+1)<<"_sampledE"<< ".txt";
            eestr2 = eebuffer2.str();
            eFileName <<str1.c_str()<< eestr2.c_str();
            std::string e_file_name = eFileName.str();
            // and so on for the 7 files .... 

            //creating the files
            ofstream pFile;
            ofstream eFile;
            // and so on for the 7 files .... 
            //opening the files
            pFile      .open (p_file_name.c_str());
            eFile        .open (e_file_name.c_str());
            // and so on for the 7 files .... 
            // then I start the writing in the files and at the end ...

            pFile.close();
            eFile.close();
}
// end of the segment loop

标准c++/C库不足以访问那么多文件。如果您试图同时访问数十万个文件,甚至BG/L/P内核也会崩溃,这与您的数字非常接近。大量的物理文件也会给并行系统带来额外的元数据。

复杂的超级计算机通常有大量专用的I/O节点——为什么不利用标准的MPI函数进行并行I/O呢?对于您想要保存的文件数量,这应该足够了。

你可以从这里开始:http://www.open-mpi.org/doc/v1.4/man3/MPI_File_open.3.php

祝你好运!

你需要自己做IOs吗?如果没有,您可以尝试HDF5库,它在使用高性能计算的科学家中非常流行。它可能是向前看一看,这可能会简化你的工作。例如,您可以在同一个文件中编写内容,从而避免数千个文件。(请注意,您的性能可能还取决于您的cluser的文件系统)

创建7个线程或进程,无论你使用什么,并将threaddid/processed附加到正在写入的文件。这样就不会有争用了

Blue Gene架构可能只剩下几年时间了,但如何实现"可扩展I/O"的问题将在一段时间内困扰我们。

首先,MPI-IO本质上是这种规模的需求,特别是集合I/O特性。尽管这篇论文是为/L写的,但其中的教训仍然是相关的:

  • collective open允许库设置一些优化
  • 集体读写可以转换为与GPFS文件系统块边界对齐的请求(这对于锁管理和最小化开销很重要)
  • "I/O聚合器"的选择和放置可以以一种注意机器拓扑的方式完成
https://press3.mcs.anl.gov/romio/2006/02/15/romio-on-blue-gene-l/

聚合器的选择在/Q上是相当复杂的,但其思想是选择这些聚合器来平衡所有可用的"系统调用I/O转发"(period)链接的I/O:

https://press3.mcs.anl.gov/romio/2015/05/15/aggregation-selection-on-blue-gene/