C++ 使用 OpenMP 任务并行化文件 I/O 和分析

标签 c++ multithreading performance parallel-processing openmp

我目前在一个系统上工作,我在其中读取超过 2 亿条记录(行)的文件,因此我认为我可以使用生产者-消费者模型来提高性能(在我阅读时工作)。但是,我没有实现强大的性能并且担心我的总体设计是错误的。将其置于上下文中:

int i = 0;
string buffer[MAX_SIZE];

//critical regions exist for map_a and map_b (shared below) in the task function 

#pragma omp parallel shared(map_a), shared(map_b), num_threads(X) 
#pragma omp single
{
    while (getline(fin, line) && !fin.eof())
    {
        buffer[i] = line;
        if (++i == MAX_SIZE)
        {
#pragma omp task firstprivate(buffer)
            work_on_data(buffer, map_a, map_b);
            i = 0;
        }
    }
}

work_on_data 中,缓冲区中的每条记录大约需要 49-95μ 的时间来处理,由于条件的差异,我怀疑 pragma omp critical 区域(一个用于每个共享 map )。对于两个关键区域:

  1. 对于 map_a :如果某个案例根据记录成立,则需要使用从记录派生的键将条目添加到映射中。如果条目已存在,则需要对其进行更新。在映射读取、潜在更新和写入上有一个临界区。
  2. 对于 map_b :对于每条记录,必须更新 map 。临界区涵盖与 (1) 相同的操作,即读取、潜在的更新/插入和写入。

所以,关于我的方法。我应该使用单独的 pthread 来缓冲 IO 吗?我是否应该简单地缓冲到一个巨大的内存分配缓冲区中,并创建 pragma omp parallel for 对其记录子集的任务?我对这种编程没有经验。

提前致谢!


编辑:澄清临界区的使用。

最佳答案

关于 IO,我认为您不会获得太多性能,因为它应该已经被操作系统很好地缓冲了。您总是可以尝试自己实现大缓冲(可能与生产者/消费者一起),或使用内存映射文件,但恐怕您会对性能提升感到失望(而且 getline 简单得多)。

关于文件分析,您当然应该尝试优化计算本身,但如果您可以删除关键区域,则可能获得更好的 yield 。通常,目标是完全消除对共享对象的依赖。你如何做取决于你的应用程序,但一般的想法是在每个线程中进行独立处理,然后将结果合并在一起。在您的情况下,您可以在每个线程中分配独立的 map ,然后再更新真实 map 。如果您需要原始 map 进行处理,请阅读它们但不要更新/写入它们,编写独立对象并稍后更新。这样您就可以删除关键区域(读取操作是线程安全的)。

作为旁注,这是非常特定于应用程序的,也是特定于硬件的。如果您的处理时间比文件读取时间短(这在很大程度上取决于您的 CPU/HDD/SSD),您可能会通过更好的 IO 缓冲获得更多性能,甚至可能使多线程变得无用。此外,如果结果合并太重,拆分结果可能不值得。如何拆分/合并结果很重要;您可以只构建一个要执行的更新列表,或者构建一个您将合并的实际 map 。关键区域也可能没有问题。尝试进行实验,看看哪种方法更适合您。

关于C++ 使用 OpenMP 任务并行化文件 I/O 和分析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27795910/

相关文章:

c++ - Q按钮 : Two different Font size

c++ - 如何通过 QtConcurrent 调用带参数的函数

multithreading - 关于作者如何在读者/作者算法中被签名

java - 当一个线程在保留锁时调用signal(),而另一个线程在await()中,谁会进入CS?

c++ - Eclipse 是否有任何增强的 gdb 控制台?

c++ - 链接/编译使用 boost/filesystem.hpp 的程序

mysql - 如何更有效地检查一个值是否出现在不同的表中?

performance - Jetpack Compose 中的字母滚动条

performance - 比较BSXFUN和REPMAT

c++ - exit() 和 abort() 有什么区别?