用C++在MPI中解析大文件

gd.*_*lva 2 c++ file mpi

我有一个C++程序,我想解析一个巨大的文件,寻找我已经实现的一些正则表达式.程序在顺序执行时工作正常但后来我想用MPI运行它.

我通过在函数中区分主服务器(协调执行的主服务器)和工作服务器(并行解析文件的服务器)来开始适应MPI .像这样的东西:

MPI::Init(argc, argv);
...

if(rank == 0) {
    ...

    // Master sends initial and ending byte to every worker
    for(int i = 1; i < total_workers; i++) {
        array[0] = (i-1) * first_worker_file_part;
        array[1] = i * first_worker_file_part;
        MPI::COMM_WORLD.Send(array, 2, MPI::INT, i, 1);
    }
}

if(rank != 0)
    readDocument();

...

MPI::Finalize();
Run Code Online (Sandbox Code Playgroud)

所述将发送到每个工人的阵列与包含在那里它将开始位置的文件的读取的字节位置2 0以及它需要停止在读取位置上的字节1.

readDocument()函数看起来像这样由现在(不解析,只是每个工人阅读他的文件的一部分):

void readDocument()
{
    array = new int[2];
    MPI::COMM_WORLD.Recv(array, 10, MPI::INT, 0, 1, status);
    int read_length = array[1] - array[0];
    char* buffer = new char [read_length];

    if (infile)
    {
        infile.seekg(array[0]); // Start reading in supposed byte
        infile.read(buffer, read_length);
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试过不同的例子,从写入到文件读取的输出到运行不同数量的进程.例如,当我用20个进程而不是10个进程运行程序时,它会持续两倍的时间来读取文件.我预计它将近一半的时间,我无法弄清楚为什么会发生这种情况.

另外,在另一个问题上,我想让主人等待所有工人完成他们的执行,然后打印最后的时间.在工人处理时,有没有办法"阻止"他?就像C pthreads中的cond_wait一样?

Hig*_*ark 5

根据我的经验,在具有并行文件系统的计算机系统上工作的人倾向于了解那些并行文件系统,因此您的问题最初标记为您不在这样的系统上工作的人.

如果没有特定的硬件支持,从单个文件读取可以归结为系统定位单个读取头并从磁盘读取一系列字节到内存.许多现代文件系统(例如RAID)的复杂现实并未实质性地改变这种情况,实际上可能存储跨多个磁盘的文件.当多个进程要求操作系统同时访问文件时,o/s根据某些概念(可能是公平性)包含磁盘访问权限,这样就不会使进程变得饥饿.在最坏的情况下,o/s花费了大量时间将磁盘访问从进程切换到进程,从而显着降低了读取速率.就吞吐量而言,最有效的方法是单个进程一次读取整个文件,而其他进程执行其他操作.

这种情况,即争用稀缺磁盘I/O资源的多个进程,无论这些进程是并行,MPI(或类似)程序的一部分还是同时运行的完全独立的程序,都适用.

影响是你观察到的 - 而不是每个等待获得自己的文件的1/10份额的10个进程,你有20个进程,每个进程等待他们的1/20分享.哦,你哭了,但是每个进程只读取了一半的数据,所以整个团队应该花费相同的时间来获取文件.不,我回答,你忘了添加o/s在访问之间定位和重新定位读/写磁头所需的时间.读取时间包括延迟(请求完成后读取开始需要多长时间)和吞吐量(I/O系统可以多快地传递字节).

应该很容易得出一些合理的延迟和带宽估计,这可以解释20个进程的读数是10的两倍.

你怎么解决这个问题?你不能,不能没有并行文件系统.但是您可能会发现让主进程读取整个文件然后将其包裹起来比您当前的方法更快.您可能不会,您可能会发现当前的方法对于整个计算来说是最快的.如果读取时间是总计算时间的10%,那么您可能会认为这是一个合理的开销.