并行化广度优先搜索

时间:2017-05-20 06:39:44

标签: c++ parallel-processing openmp breadth-first-search

我刚刚自学了一些OpenMP,这可能是愚蠢的。基本上我正试图在c ++中并行化广度优先搜索程序,每个节点需要很长时间才能处理。这是一个示例代码:

File logf = new File("log1.txt");
Boolean bb = logf.exists();
if(!bb)
try {
bb = logf.createNewFile();
} catch (IOException e) {
msg.setText("not able to create file.");
}

处理函数doStuff()非常昂贵,我想并行化它。但是,如果我通过将queue<node*> q; q.push(head); while (!q.empty()) { qSize = q.size(); for (int i = 0; i < qSize; i++) { node* currNode = q.front(); q.pop(); doStuff(currNode); q.push(currNode); } } 放在for行之前来并行化for循环,那么在运行时会弹出各种奇怪的错误。我猜测的原因是这种方式#pragma omp parallel forq.front()也会被并行化,多个线程可能会通过q.push()获得相同的节点(因为它们都在任何{之前得到了处理} {1}}已处理完毕)。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:4)

解决方案是使用关键部分保护对队列的访问。

queue<node*> q;
q.push(head);
while (!q.empty()) {
  qSize = q.size();
  #pragma omp parallel for
  for (int i = 0; i < qSize; i++) {
    node* currNode;
    #pragma omp critical
    {
      currNode = q.front();
      q.pop();
    }
    doStuff(currNode);
    #pragma omp critical
    q.push(currNode);
  }
}

这与使用通用互斥锁并将其锁定类似。

此版本的效率存在一些限制:在for循环结束时,尽管工作在队列中,但某些线程可能处于空闲状态。在处理队列为空但有些线程仍处于计算状态的情况下,制作一个线程在队列中存在某些东西的情况下继续工作的版本。

根据节点中涉及的数据大小,您可能还会对缓存效果和错误共享产生重大性能影响。但这不能用具体的例子来讨论。在许多情况下,简单版本可能足够有效,但获得最佳性能可能会变得任意复杂。

在任何情况下,您都必须确保doStuff不会修改任何全局或共享状态。