Fre*_*Foo 2 c c++ parallel-processing openmp
我编写了一个必须处理大量数据的C++应用程序.使用OpenMP我很好地并行化了处理阶段,并且令人尴尬地发现输出写入现在是瓶颈.我决定也使用parallel for那里,因为我输出项目的顺序是无关紧要的; 它们只需要输出为连贯的块.
下面是输出代码的简化版本,显示除"两个自定义迭代器"中的两个自定义迭代器之外的所有变量.我的问题是:这是解决这个问题的正确和最佳方法吗?我读到了关于barrierpragma的内容,我需要它吗?
long i, n = nrows();
#pragma omp parallel for
for (i=0; i<n; i++) {
std::vector<MyData> related;
for (size_t j=0; j < data[i].size(); j++)
related.push_back(data[i][j]);
sort(related.rbegin(), related.rend());
#pragma omp critical
{
std::cout << data[i].label << "\n";
for (size_t j=0; j<related.size(); j++)
std::cout << " " << related[j].label << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
(我标记了这个问题,c因为我认为OpenMP在C和C++中非常相似.如果我错了,请纠正我.)
解决输出争用的一种方法是将线程本地输出写入字符串流(可以并行完成),然后将内容推送到cout(需要同步).
像这样的东西:
#pragma omp parallel for
for (i=0; i<n; i++) {
std::vector<MyData> related;
for (size_t j=0; j < data[i].size(); j++)
related.push_back(data[i][j]);
sort(related.rbegin(), related.rend());
std::stringstream buf;
buf << data[i].label << "\n";
for (size_t j=0; j<related.size(); j++)
buf << " " << related[j].label << "\n";
#pragma omp critical
std::cout << buf.rdbuf();
}
Run Code Online (Sandbox Code Playgroud)
这提供了更细粒度的锁定,并且性能应该相应地增加.另一方面,这仍然使用锁定.另一种方法是使用流缓冲区数组,每个线程一个,并在并行循环后cout按顺序推送它们.这具有避免昂贵锁定的优点,并且输出必须被串行化.cout
另一方面,您甚至可以尝试省略critical上面代码中的部分.根据我的经验,这是有效的,因为底层流有自己的控制并发的方式.但我相信这种行为是严格的实现定义而不是可移植的.