问题主要涉及在大型(> 20GB)数据文件上计算某些函数void lineProcess(string, string&, int[])
,计算量非常大,并且还非常依赖于输入行的长度和数组参数引入的一些随机性所以我在几次试运行中的平均时间。第一个参数是文件的一行,第二个是字符串的地址,因此可以输出结果。输出的总大小为3MB。不要求第k行输入和输出对应。除了文件io之外,它听起来非常适合并行化,所以这里是代码。
void foo(const int param[]) {
// process some stuff ...
// create input stream fin, output stream fout from <iostream>
string result;
for (string line; getline(fin, line);) {
#pragma omp parallel task firstPrivate(result)
lineProcess(line, result, param);
fout << result << endl;
}
#pragma omp task wait
fin.close();
fout.close();
}
我已经在笔记本电脑上运行了几次(i7 Quad核心,应该支持8个超线程进程)并且似乎没有看到很快的速度。串行处理(即上述减去pragama指令)平均约为2800秒/行,平行约为2000秒/行。我的目标是〜600秒/线的数字。我认为问题的一部分可能是openMP实现,使用任务和taskwait但是因为我不知道文件中的行数我无法看到使用#pragma omp for
的简单方法。
理想情况下,我正在尝试读取行的缓冲区和一个结果,并且处理所有线程,直到一个缓冲区几乎为空/满,然后线程通过读/写磁盘交换到重新填充/清空它,但是我&#39;我不确定这是否可以在OpenMP中执行,或者我是否可以使用一个线程在读/写之间进行交换来执行此操作的简单版本。
任何关于为什么这不像预期的那样快或者提高性能的方法的建议将不胜感激。显然,必须读取/写入大量数据存在基本限制,但我知道线路处理也占用了相当大的时间。
我使用非常类似的方法找到了这个问题openmp - while loop for text file reading and using a pipeline第一个答案与我的代码匹配得很好,但第二个答案似乎是使用缓冲区但是我不确定如何完全适应它或者它是否&值得一试。
答案 0 :(得分:0)
您应该在for循环之前打开并行区域。这将生成一个运行多个线程的并行区域。在您创建任务时,有线程可以运行并准备好接受您的任务。
#pragma omp parallel
{
#pragma omp single
{
for(...)
{
#pragma omp task
lineProcess(...)
fout ...
}
}
#pragma omp taskwait
}
这里首先打开并行区域,然后声明下面的内容仅由一个生成任务的线程生成,而这些任务又由多个线程处理。处理完所有行后(taskwait),可以继续执行普通代码。
另外,请注意,只有lineProcess函数才是一项任务。在生成该任务(未完成或尚未完成)之后,您的生成线程将移动到fout行并对其进行处理。你可以像这样解决它:
#pragma omp task
{
lineProcess(...)
fout ...
fout.flush();
}