我正在为HiQ编写一个程序,我正在使用这个深度优先搜索循环。但是我想与MPI并行执行,但是我可以做些什么来使深度优先搜索并行?
bool FindSolution(ConfigType PuzzleConfig ) // Depth-First Search for sol to puzzle
{
if (PuzzleConfig == SolutionConfig) return true;
bool SolutionFound = false;
Mark(PuzzleConfig);
// For all configurations adjacent to current Puzzle Configuration (uses brute-force)
for (short from=1; !SolutionFound && from<=NUMHOLES; from++)
{
for (short to=1; !SolutionFound && to<=NUMHOLES; to++)
{
JumpType jump = {from,to};
if ( ValidJump(jump, PuzzleConfig) )
{
ConfigType NewConfig = FindNewConfig(jump, PuzzleConfig);
if ( !Marked(NewConfig) )
{
SolutionFound = FindSolution( NewConfig ); // Recursive call for Depth-First Search
if (SolutionFound)
JumpStack.push(jump);
}
}
}
}
return SolutionFound;
}
答案 0 :(得分:2)
当您可以提前定义并行计算元素的具体拓扑时,MPI非常有用,并且可以在执行之前将工作划分为多个计算元素。然后,每个元素“知道”其他元素所在的位置,并且大致知道它们正在做什么,从而可以决定它应该发送消息以发出MPI发送。同样,接收元素必须“知道”它们是关于接收消息,以便发出MPI接收。
深度优先搜索可以说是树状的,所以你知道抽象拓扑...但你不知道树的实际形状,因此没有处理器事先知道它与哪个节点相关联。因此很难确定哪些处理器应该发送,哪些应该接收。我不认为MPI是你的朋友。
最好有一个工作清单样式算法,它包含要搜索的扩展树的节点。然后,每个处理器可以进入工作清单,获取节点,将该节点扩展为子节点,并将子节点放回工作列表中。这将提供一个随机扩展而不是首先扩展的边界。
要首先深入,寻找工作的节点希望工作队列为其提供最深扩展节点,因此工作列表应该像优先级队列一样。这样,最深的节点首先由处理器扩展,给出深度第一的味道。
通过扩展树节点的处理器,将扩展集推送到工作列表的顶部,可以最简单地实现此效果;然后每个处理器从工作列表顶部的集合中获取工作。当处理器在工作列表顶部找到一个空集时,它可以再次尝试弹出该集。
工作窃取版本会为您带来这种效果。第一个处理器生成一组工作;如果它在生成某个节点P的子节点时有很多工作,它会停止生成P的子节点,留下一些工作来生成P的其余子节点,并将其注意力转移到已经生成的P的子节点。这给出了深度优先效果。其他节点在工作时执行相同的方式;当他们不这样做时,他们会从另一个节点窃取工作列表条目,这使他们开始搜索一个子树。