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

时间:2015-01-06 09:43:12

标签: 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;
        }
    }
}

缓冲区中的每条记录大约需要49-95μ才能在work_on_data中处理,由于条件差异而我会怀疑pragma omp critical区域(每个共享地图一个)。对于两个关键区域:

  1. 对于map_a:如果某个案例根据记录成立,则需要使用从记录派生的键将一个条目添加到地图中。如果条目已存在,则需要更新。地图读取,潜在更新和写入都有一个关键区域。
  2. 对于map_b:对于每条记录,必须更新地图。关键区域包括与(1)相同的动作,即读取,潜在的更新/插入和写入。
  3. 所以,关于我的方法。我应该使用单独的pthread来缓冲IO吗?我应该简单地缓冲到一个巨大的内存分配缓冲区并创建pragma omp parallel for在其记录的子集上的任务吗?我对这种编程没有经验。

    提前致谢!


    修改:明确使用关键区域。

1 个答案:

答案 0 :(得分:2)

关于IO,我不认为你可以获得太多性能,因为它应该已经被OS体面地缓冲了。你总是可以尝试自己实现大缓冲(可能是生产者/消费者),或者使用内存映射文件,但我担心你会对性能提升感到失望(并且getline非常简单)。

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

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