我已经实现了我的第一个 GridGain 应用程序,但没有得到预期的性能改进。可悲的是它更慢。我需要一些帮助来改进我的实现,以便它可以更快。
我的应用程序的要点是我正在使用数百万个可能的参数进行蛮力优化,每个函数评估只需几分之一秒。我通过将数百万次迭代分成几个组来实现这一点,每个组都作为一个作业执行。
相关的代码如下。函数 maxAppliedRange 为范围 x 中的每个值调用函数 foo,并返回最大值,结果成为每个作业找到的所有最大值中的最大值。
scalar {
result = grid !*~
(for (x <- (1 to threads).map(i => ((i - 1) * iterations / threads, i * iterations / threads)))
yield () => maxAppliedRange(x, foo), (s: Seq[(Double, Long)]) => s.max)
}
我的代码可以在一台机器上的多线程执行之间进行选择,也可以使用上面的代码使用多个 GridGain 节点。当我运行 gridgain 版本时,它一开始会变得更快,但是总会发生一些事情:
- 其中一个节点(在另一台机器上)错过了心跳,导致我的主计算机上的节点放弃该节点并再次开始执行作业。
- 错过心跳的节点继续做同样的工作。现在我有两个节点在做同样的事情。
- 最终,所有作业都在我的主机上执行,但由于某些作业开始较晚,因此完成所有作业需要更长的时间。
- 有时GridGain会抛出异常,因为节点超时并且整个任务失败。
- 我很生气。
我尝试将它设置为有很多作业,所以如果一个失败了,那也没什么大不了的,但是当我这样做时,我最终会在每个节点上执行许多作业。这给每台机器带来了更大的负担,使得节点更有可能错过心跳,从而导致一切更快地走下坡路。如果我每个 CPU 有一个作业,那么如果一个作业失败,则必须从头开始另一个节点。反正我赢不了。
我认为最好的方法是如果我能做两件事:
- 增加心跳的超时时间
- 限制每个节点,使其一次只执行一项工作。
如果我能做到这一点,我可以将我的任务分成许多工作。每个节点一次只做一项工作,没有机器会因为负担过重而错过心跳。如果一项工作失败,那么几乎不会丢失任何工作,并且恢复会很快。
谁能告诉我该怎么做?我应该在这里做什么?