Multithreading Optaplanner:并行求解时,随机非常低的“平均每秒计算计数”

Multithreading Optaplanner:并行求解时,随机非常低的“平均每秒计算计数”,multithreading,optimization,optaplanner,Multithreading,Optimization,Optaplanner,我使用Optaplanner来解决一个相对较小的优化问题。对于我的用例,许多这样的优化是必需的,这就是我开始并行运行它们的原因。并行性基于Java8的并行流。它不允许控制要使用的线程的实际数量,但我相信它是基于可用的CPU计数的 对于大多数解算器运行来说,这似乎很好,但我注意到,有时我从一次运行中得到无效的解决方案,当仅运行该问题时,这些解决方案是不可复制的 在检查日志之后,我注意到,对于无效解决方案,平均每秒计算计数非常低,而对于其他运行,则可以。事实上,无效的解决方案实际上是原始构建的初始解

我使用Optaplanner来解决一个相对较小的优化问题。对于我的用例,许多这样的优化是必需的,这就是我开始并行运行它们的原因。并行性基于Java8的并行流。它不允许控制要使用的线程的实际数量,但我相信它是基于可用的CPU计数的

对于大多数解算器运行来说,这似乎很好,但我注意到,有时我从一次运行中得到无效的解决方案,当仅运行该问题时,这些解决方案是不可复制的

在检查日志之后,我注意到,对于无效解决方案,平均每秒计算计数非常低,而对于其他运行,则可以。事实上,无效的解决方案实际上是原始构建的初始解决方案:

[rkJoinPool.commonPool-worker-6] (DefaultSolver.java:203)       Solving started: time spent (0), best score (-5hard/-2medium/168soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
[rkJoinPool.commonPool-worker-6] (DefaultConstructionHeuristicPhase.java:158) Construction Heuristic phase (0) ended: step total (0), time spent (1), best score (-5hard/-2medium/233soft).
[rkJoinPool.commonPool-worker-4] (DefaultSolver.java:203)       Solving started: time spent (1), best score (-5hard/-1medium/579soft), environment mode (REPRODUCIBLE), random (JDK with seed 0). 
[rkJoinPool.commonPool-worker-4] (DefaultConstructionHeuristicPhase.java:158) Construction Heuristic phase (0) ended: step total (0), time spent (1), best score (-5hard/-1medium/617soft).
[rkJoinPool.commonPool-worker-5] (DefaultSolver.java:203)       Solving started: time spent (1), best score (-6hard/-3medium/137soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
[rkJoinPool.commonPool-worker-7] (DefaultLocalSearchPhase.java:152) Local Search phase (1) ended: step total (42), time spent (704), best score (0hard/0medium/808soft).
[rkJoinPool.commonPool-worker-4] (DefaultLocalSearchPhase.java:152) Local Search phase (1) ended: step total (22), time spent (218), best score (0hard/0medium/1033soft). 
[rkJoinPool.commonPool-worker-5] (DefaultSolver.java:238)       Solving ended: time spent (210), best score (-6hard/-3medium/137soft), average calculate count per second (4), environment mode (REPRODUCIBLE).
[rkJoinPool.commonPool-worker-7] (DefaultSolver.java:238)       Solving ended: time spent (746), best score (0hard/0medium/808soft), average calculate count per second (25256), environment mode (REPRODUCIBLE).
[rkJoinPool.commonPool-worker-4] (DefaultSolver.java:238)       Solving ended: time spent (219), best score (0hard/0medium/1033soft), average calculate count per second (30461), environment mode (REPRODUCIBLE).
请注意线程4和线程7如何在25-30k ACC中产生良好的结果,而线程5产生无效的结果,并且在200毫秒终止超时的情况下只使用了4个ACC。我假设实际上只执行了一个步骤

使用了以下配置,这是使用基准测试仪确定的,尽管是在单线程设置中:

<termination>
    <millisecondsSpentLimit>2000</millisecondsSpentLimit>
    <unimprovedMillisecondsSpentLimit>200</unimprovedMillisecondsSpentLimit>
</termination>
<constructionHeuristic>
    <constructionHeuristicType>FIRST_FIT</constructionHeuristicType>
</constructionHeuristic>
<localSearch>
    <localSearchType>HILL_CLIMBING</localSearchType>
</localSearch>
我假设这个问题与以下事实有关:当使用基于时间的终止条件时,多个解算器并行运行。终止时间是基于墙时间还是基于实际CPU时间

在并行运行时,使用基于时间的终止条件不是一个好主意吗?这似乎是使用所有可用计算能力的最佳方式。 是什么导致单个解算器看似随机地只执行很少的步骤?

毫秒PentLimit和UnmovedMillisecondsPentLimit基于墙时间,而不是实际的CPU时间


顺便说一句,并行流不会将线程数限制为CPU数,因为这些作业可能会在IO下阻塞,而Solver.solve调用则不是这样。我更喜欢使用线程池大小为Math.max1、Runtime.getRuntime.availableProcessors-2的ExecutorService。

您想做什么?多赌注解决?爬山通常不如禁忌搜索、迟到等等。我正试图从一支可用的球队中建立一份足球运动员名册。这是一个模拟的一部分,在这个模拟中,对不同的球队和比赛进行了一次又一次的模拟。我将不得不再次研究提到的元启发式——我认为它们在benchmarker.TS和LA do中根本不起作用。SA在没有额外配置的情况下无法运行。我将尝试此功能。老实说,我只使用了基于流的并行性,因为它是最容易实现的。作为替代方案,使用基于步骤的终止标准会更好吗,如本文所述?是的。虽然scoreCalucationLimit在TS和LA之间可能更公平,因为TS是慢步,LA是快步。我重新运行并扩展了我的基准测试,特别是专注于为每个元启发式找到一个好的配置。结果证明,禁忌搜索为我的问题提供了更可靠的结果,尽管爬山和其他方法并没有那么糟糕。最后,我没有选择分数计算限制,只是选择了一个未改进的500毫秒的dmillisecondslimit。通过这种配置,我没有再看到问题。关于流和线程数的主题,我遵循以下建议: