我有一个 C++ 程序,我想在其中解析一个大文件,寻找我已经实现的一些正则表达式。该程序在按顺序执行时工作正常,但后来我想使用 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();
master 将向每个 worker 发送一个包含 2 个位置的数组,其中包含它将开始读取位置 0中的文件的字节strong> 和它需要在位置 1 停止读取的字节。
readDocument() 函数现在看起来像这样(不是解析,只是每个 worker 读取他的文件部分):
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);
}
}
我尝试过不同的示例,从将读取的输出写入文件到使用不同数量的进程运行它。发生的情况是,当我使用 20 个进程而不是 10 个进程运行程序时,例如,它会持续两倍的时间来读取文件。我预计它会是将近一半的时间,但我不明白为什么会这样。
此外,在另一件事上,我想让 master 等待所有 worker 完成他们的执行,然后打印最后的时间。有什么办法可以在 worker 们加工的时候“屏蔽”他吗?就像 C pthreads 中的 cond_wait 一样?
最佳答案
根据我的经验,在具有并行文件系统的计算机系统上工作的人往往了解那些并行文件系统,因此您的问题最初将您标记为不在此类系统上工作的人。
如果没有特定的硬件支持,从单个文件读取归结为系统定位单个读取头并将字节序列从磁盘读取到内存。许多现代文件系统(例如 RAID)的复杂现实并没有实质性地改变这种情况,RAID 实际上可能将文件存储在多个磁盘上。当多个进程同时请求操作系统访问文件时,o/s 根据某种概念(可能是公平的)分配磁盘访问,这样就没有进程会饿死。在最坏的情况下,o/s 花费太多时间在进程之间切换磁盘访问,导致读取速率显着下降。就吞吐量而言,最有效的方法是让单个进程一次性读取整个文件,而其他进程则做其他事情。
这种情况下,多个进程争用稀缺的磁盘 i/o 资源,适用于这些进程是并行、MPI(或类似)程序的一部分还是同时运行的完全独立的程序。
影响是您所观察到的——而不是 10 个进程每个等待获得它们自己的 1/10 份额的文件,而是 20 个进程每个等待它们的 1/20 份额。哦,你哭了,但是每个进程只读取一半的数据,所以整个团队应该花费相同的时间来获取文件。不,我回答说,您忘记添加 o/s 在访问之间定位和重新定位读/写磁头所花费的时间。读取时间包括延迟(发出请求后需要多长时间才能开始读取)和吞吐量(I/O 系统来回传递字节的速度)。
应该很容易得出一些合理的延迟和带宽估计值,以解释 20 个进程的读取时间是 10 个进程的两倍。
你怎么解决这个问题?你不能,不是没有并行文件系统。但是您可能会发现让主进程读取整个文件然后将其打包比您当前的方法更快。你可能不会,你可能只是发现当前的方法对你的整个计算来说是最快的。例如,如果读取时间占总计算时间的 10%,您可能会认为这是一个可以接受的合理开销。
关于c++ - 在 C++ 中使用 MPI 解析大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26380678/