2010-12-06 25 views
1

我正在制作一个系统。这是一个复杂的系统,但它归结为一个Solver类这样的方法:该方法有望如何让此Java代码可并行化?我如何使它变得易变

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 

的问题是我想在大量问题上运行这一点,不想永远等待结果。所以说,我有一百万的测试问题,我想在测试中它需要我做一杯茶的时间内完成,我有两个问题:

  1. 说我有一万芯处理器和实例Solver是线程安全的,但没有锁定(它们是不可变的或其他),并且它们所做的所有计算都在内存中(即没有磁盘或网络或其他内容)。我可以用线程安全列表替换解决方案列表并启动线程来解决每个问题,并期望它更快吗?快多少?它可以在5秒内运行吗?

  2. 是否有一个体面的云计算服务在那里的Java,我可以购买500万秒的时间,让这个代码运行在五秒钟?我需要做什么来准备我的代码以在这样的云上运行?无论如何,500万秒的成本是多少?

谢谢。

回答

0

你在问非常大的问题。线程的开销很大,需要注意的一点是它们在父进程中运行。如果你想同时运行一百万个解算器,你必须将它们分解到他们自己的进程中。

0

您可以对每个输入使用一个程序,然后使用像Condor(用于Linux)或HPC(用于Windows)的简单批处理调度程序。你也可以在亚马逊上运行它们,但是有一些学习曲线,它不仅仅是“上传Java代码&”。

0
  1. 当然,您可以使用标准的工作线程范例并行运行。但是会有一些同步开销(例如,当解决方案列表更新会在所有事情尝试同时完成时导致锁争用),因此它不会在5秒内运行。但速度将超过500万秒:-)
  2. 根据您需要多少CPU(请参阅pricing),Amazon EC2每小时运行价格为0.085至0.68美元。所以,大约120美元。当然,你需要设置一些独立的东西来分配各种CPU的工作。一种选择可能只是使用Hadoop的(见是否Hadoop is right for running simulations这个问题。

您可以阅读之类的东西Guy Steele's talk on parallelism关于如何思考平行的详细信息。

0

查阅这些文章并发:

基本上,Java 7中的新叉/加入模型将工作得很好了这种方法。从本质上讲,您可以设置您的百万个任务,并将它们尽可能扩展到所有可用的处理器。您将不得不提供您的自定义“云”任务执行程序,但可以完成。

这当然假设你的“求解”算法是平行的。简而言之,只要Solver是完全独立的,它们应该能够在任意数量的处理器之间分割。

1

你已经表达了你的问题有两个主要的序列化问题:问题产生和解决方案消耗(目前表示为整数列表)。你想尽快得到第一个问题(目前在产生所有问题之前你不会得到它们)。

我假设问题列表顺序和解决方案列表顺序之间存在关联 - 即solutions.get(3)problems.get(3)的解决方案 - 这对于并行化是一个巨大的问题。你最好有一个问题/解决方案Pair<P, S>,所以你不需要保持相关性。并行化求解器方法并不困难,尽管你如何做到这一点将取决于每个求解方法的计算成本(通常这种方法越昂贵,平行化开销成本越低,所以如果这些成本是非常便宜,你需要批量他们)。如果最终采用分布式解决方案,那么当然会有更高的成本。 Executor框架和fork/join扩展将是一个很好的起点。