并行化广度优先搜索
Parallelizing a Breadth-First Search
我刚刚自学了一些OpenMP,这可能很愚蠢。基本上,我正在尝试在 c++ 中并行化广度优先搜索程序,每个节点都需要很长时间来处理。下面是一个示例代码:
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);
}
}
处理函数doStuff((非常昂贵,我想并行化它。但是,如果我通过将 for 行放在 for 行之前来并行化 for 循环#pragma omp parallel for
,则在运行时会弹出各种奇怪的错误。我猜原因是这样q.front()
和q.push()
也会并行化,多个线程可能会通过q.front()
获得同一个节点(因为它们都在处理任何q.push
之前被处理(。
我该如何解决这个问题?
解决方案是使用关键部分保护对队列的访问。
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
不会修改任何全局或共享状态。
相关文章:
- 提升图广度优先搜索前置编译错误
- 使用openmp实现并行广度优先搜索
- 广度优先搜索陷入无限循环
- 并行化广度优先搜索
- 如何使用C 中的广度优先搜索解决8个式嘴问题
- 如何使用广度优先搜索确定是否可以在有向图中到达顶点
- 修改广度优先搜索算法以记住矩阵中的最短路径
- 如何实现广度优先搜索
- 图论:广度优先搜索
- 广度优先搜索未找到正确的路径
- 有向图中的广度优先搜索
- 使用Boost图库从多个来源进行广度优先搜索
- 如何用C++编写广度优先搜索的代码
- C++以广度优先搜索的方式查找多个数组中元素的所有组合
- 广度优先搜索:有向图
- 邻接列表,用于创建图形和广度优先搜索 (BFS) 和 Fepth First Search (DFS)
- 广度优先搜索中的 C++ 迭代器和指针用法
- 广度优先搜索输入
- 广度优先搜索返回错误的金额
- 是否可以将boost库的广度优先搜索算法应用于矩阵