【问题标题】:How to parallelize a negamax algorithm?如何并行化一个负最大算法?
【发布时间】:2018-02-25 16:54:59
【问题描述】:
有没有办法并行化下面的 negamax 算法?
01 function negamax(node, depth, color)
02 if depth = 0 or node is a terminal node
03 return color * the heuristic value of node
04 bestValue := −∞
05 foreach child of node
06 v := −negamax(child, depth − 1, −color)
07 bestValue := max( bestValue, v )
08 return bestValue
【问题讨论】:
标签:
algorithm
parallel-processing
artificial-intelligence
negamax
【解决方案1】:
当这样表述为单个递归函数时,并不容易。
最简单的方法是将其拆分为两个函数:一个专门用于您在树根处的第一次调用,然后另一个函数被调用并递归地继续调用自身。在根版本中,您可以通过子级并行化循环,并将不同的值存储在列表中。然后你只需要一个非并行循环来从列表中找到最大值,但这会立即完成。
请注意,如果您继续进行 alpha-beta 修剪等增强功能,这将变得更加复杂;像我在这里建议的那样天真地并行化第一个循环将显着减少可以通过 alpha-beta 修剪进行修剪的节点数量
【解决方案2】:
鉴于树形拓扑,递归公式的使用不是一个原因,而是一个结果的因果关系,因为递归公式很容易绘制和编码。 (对于那些真正对计算机科学感兴趣的人,只需对递归公式计算策略的资源消耗进行基准测试,并在 [SPACE]- 和 [TIME]- 中进行测试域)多快开始产生麻烦,一旦你的基准扩展有点超出教科书示例问题规模和/或超出设计人员在这个资源限制的困境中如何公平地期望和设置深度递归级别的选择如果递归尝试深入一步,那么接下来会发生什么,而不是这个“预先连接的”玻璃天花板确实发生了)。
关于找到真-[PARALLEL] 处理策略的机会的问题直接决定于找到不可并行的纯-[SERIAL] 依赖链,该依赖链从每个终端节点开始并向后进展,朝向树根-节点。
树拓扑需要某种相互依赖的“通信”,这种“通信”出现在树的反向遍历期间,因此 true-[PARALLEL] 处理计划可能允许的所有主要优势都在这种需要时有效地丢失了将纯-[SERIAL] 值依赖链的产物转移到“下一个”非本地处理代码流执行。这使得最初的想法成为反模式。
在意识到这个主要是纯-[SERIAL] 依赖后,任何想要并行化的强制尝试仍然是可能的,但其性能结果变得更像是一种反模式,而不是任何合理支持的选择,因为它们实际上会花费更多(在 @987654337 @-domain ),而不是串行链处理(是否递归地制定),因为[SPACE]-domain 允许这种作案方式。