我正在研究一个系统。这是一个复杂的系统,但它归结为一个Solver
类,其方法如下:
public int solve(int problem); // returns the solution, or 0 if no solution found
现在,当系统启动并运行时,此方法的运行时间大约为5秒,并且非常快。但是,我计划运行一些看起来有点像这样的测试:
List<Integer> problems = getProblems();
List<Integer> solutions = new ArrayList<Integer>(problems.size);
Solver solver = getSolver();
for (int problem: problems) {
solutions.add(solver.solve(problem));
}
// see what percentage of solutions are zero
// get arithmetic mean of non-zero solutions
// etc etc
问题是我想在大量问题上运行它,并且不想永远等待结果。所以说我有一百万个测试问题,我希望测试能够在我喝茶的时候完成,我有两个问题:
假设我有一百万个核心处理器并且Solver
的实例是线程安全但没有锁定(它们是不可变的或者其他东西),并且它们所做的所有计算都在内存中(即没有磁盘或网络或其他东西发生)。我可以用线程安全列表替换解决方案列表并启动线程来解决每个问题并期望它更快吗?多快了?可以在5秒内运行吗?
是否有适合Java的云计算服务,我可以购买500万秒的时间并让这段代码在5秒内运行?我需要做些什么来准备我的代码才能在这样的云上运行?无论如何,500万秒的费用是多少?
感谢。
答案 0 :(得分:1)
您已经表达了两个主要的序列化问题:问题产生和解决方案消耗(目前表示为整数列表)。你想尽快得到第一个问题(目前你不会得到它们直到产生所有问题)。
我也假设问题列表顺序和解决方案列表顺序之间存在关联 - solutions.get(3)
是problems.get(3)
的解决方案 - 这对于并行化来说将是一个巨大的问题。您最好有Pair<P, S>
问题/解决方案,这样您就不需要保持相关性。
求解器方法的并行化并不困难,尽管如何操作将在很大程度上取决于每种求解方法的计算成本(通常方法越昂贵,并行化的开销成本越低,所以如果这些非常便宜你需要批量他们)。如果最终得到分布式解决方案,那么当然会有更高的成本。 Executor
框架和fork / join扩展将是一个很好的起点。
答案 1 :(得分:0)
你问的是非常大的问题。线程有开销,需要注意的一点是它们在父进程中运行。如果你想同时运行一百万个这样的求解器,你必须将它们分成自己的进程。
答案 2 :(得分:0)
您可以为每个输入使用一个程序,然后使用简单的批处理调度程序,如Condor(适用于Linux)或HPC(适用于Windows)。你也可以在亚马逊上运行那些,但是有一点学习曲线,它不仅仅是“上传Java代码并且去”。
答案 3 :(得分:0)
您可以阅读Guy Steele's talk on parallelism之类的内容,了解有关如何思考并行的更多信息。
答案 4 :(得分:0)
查看这些关于并发性的文章:
基本上,Java 7的新Fork / Join模型对这种方法非常有效。从本质上讲,你可以设置你的百万+任务,它将尽可能地扩散它们所有可用的处理器。您必须提供自定义的“云”任务执行程序,但可以完成。
当然,这假设您的“求解”算法是非常平行的。简而言之,只要Solver完全独立,它们就可以在任意数量的处理器之间进行分割。
答案 5 :(得分:0)