【问题标题】:Divide a list of numbers into smaller list with "sum" approximately same将数字列表划分为较小的列表,“总和”大致相同
【发布时间】:2010-01-29 18:01:45
【问题描述】:

我在网格上执行了大约 2000 个测试,每个测试在网格上作为单独的任务运行。测试确实有相当长的启动时间。总执行时间为 500 小时,在 60 个节点的 SunGridEngine 上不到 10 小时完成。测试的运行时间从 5 分钟到 90 分钟不等。在没有太多智能的情况下组合测试会带来一些性能提升。我想创建大小大致相等的“任务”。我该怎么做?

(我们现在要做的:对所有测试进行排序并不断添加,直到执行时间总和约为 5 小时。寻找更好的东西)

【问题讨论】:

  • 你到底要什么?一种算法来获取数字列表并将它们放入桶中,平衡每个桶中数字的总和?

标签: java algorithm graph grid set


【解决方案1】:

以最佳方式执行此操作是 NP 完全的。这是partition problem 的变体,它是subset sum problem 的一个特例,它本身就是knapsack problem 的一个特例。

在您的情况下,您可能不需要精确的解决方案,因此您可以使用一些启发式方法在合理的时间内获得“足够好”的东西。有关一些方法的描述,请参阅分区问题页面的Methods 部分。

【讨论】:

    【解决方案2】:

    您正在寻找的是 k 个集合的分区问题。

    有一些关于 k=3 的文献,称为 3 分区问题。这是强意义上的NP完全。

    有许多启发式方法可以快速给出近似结果。

    我建议你从这里开始:http://en.wikipedia.org/wiki/Partition_problem

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      这是子集和问题的a version,并且是 NP 完全的。你最好的选择是雇佣一些subset-sum heuristics

      【讨论】:

        【解决方案4】:

        您的问题听起来有点像车间调度问题。有各种不同的测序方法,其中一些在here 中进行了描述。例如,按照处理时间的递增顺序进行排序将最小化平均等待时间和一大堆其他措施。如果您详细说明目标、设置时间、处理时间以及任何有帮助的相互依赖关系。

        【讨论】:

          【解决方案5】:

          看着 Laurence 发布的链接,我想我会尝试做点什么。该算法是将最长的测试分配给最短的任务列表(重复直到分配了所有测试)。使用您的示例和随机测试时间,std 偏差非常低,多次运行不到 2 分钟(C# 中的代码,但没有什么不是简单的转换):

              private static void BuildJobs()
              {
                  PriorityQueue<Task> tasks = new PriorityQueue<Task>();
          
                  //create a task list for each node
                  for (int i = 0; i < 60; i++)
                  {
                      Task t = new Task();
                      tasks.Enqueue(t);
                  }
          
                  //get the list of tests, in order from longest to shortest
                  int[] testList = new int[2000];
          
                  for (int i = 0; i < testList.Length; i++)
                  {
                      testList[i] = random.Next(5, 90);
                  }
          
                  Array.Sort<int>(testList);
                  Array.Reverse(testList);
          
                  // add the longest running test to the current shortest task list
                  foreach (int time in testList)
                  {
                      Task t = tasks.Dequeue();
                      t.addTest(time);
                      tasks.Enqueue(t);
                  }
          
                  Debug.WriteLine(CalculateStdDev(tasks));
          
              }
          

          【讨论】:

            猜你喜欢
            • 2010-10-27
            • 2011-05-08
            • 2011-06-23
            • 2014-05-25
            • 2012-07-12
            • 2011-11-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多