我是并行编程的初学者(除了编写一些基本的多线程事物之外,我没有做过任何事情)我需要并行化一些多线程java代码以使其运行得更快。多线程算法只生成线程并将它们传递给操作系统,操作系统为我分配线程。每个线程的结果可以由一些收集器收集,该收集器还处理信号量等的同步问题并计算所有不同线程的结果的总和。多线程代码有点像这样:
public static void main(String[] args) {
int numberOfProcesses = Integer.parseInt(args[0]);
...
Collector collector = new Collector(numberOfProcesses);
while(iterator.hasNext()) {
Object x = iterator.next();
new OverwrittenThread(x, collector, otherParameters).start();
}
if(collector.isReady())
System.out.prinltn(collector.getResult());
}
我的第一个想法是将它转换为MPI,这是基本的方法(我猜)只是拆分循环并将此循环的每次迭代都给这样的另一个处理器(使用mpiJava):
public static void main(String[args]) {
...
Object[] foo = new Object[number];
int i = 0;
while(iterator.hasNext())
foo[i++] = iterator.next();
...
int myRank = MPI.COMM_WORLD.Rank();
for(int i = myRank; i < numberOfElementsFromIterator; i += myRank) {
//Perform code from OverwrittenThread on foo[i]
}
MPI.COMM_WORLD.Reduce(..., MPI.SUM, ...);
}
直到现在,作为mpi中的新手,我唯一可以让事情发挥作用的方式。这只是一个想法,因为我不知道如何解决实现问题,如将BigIntegers转换为MPI数据类型等等。(但我想这会得到这个,我猜)
真正的问题但是,这种解决问题的方法使得工作分配非常不平衡,因为它没有考虑某个迭代需要多少工作量。这可能会导致一些麻烦,因为一些迭代可以在不到一秒的时间内完成,而其他迭代可能需要几分钟。
有没有办法在MPI实现中获得类似多线程版本的方法?起初我认为它只是很多非阻塞的点对点通信,但我没有看到让它以这种方式工作的方法。我也考虑过使用分散功能,但我在理解如何正确使用它时遇到了太多麻烦。
有人可以帮我解决这个问题吗? (我确实理解基本的C等)
提前致谢
答案 0 :(得分:1)
将多线程程序转换为分布式程序时,首先要问自己的是:
我想通过跨多个核心/节点/等分发数据来实现什么目标?
人们在开始使用MPI时遇到的最常见问题之一就是认为他们可以在一个小的共享内存环境(即单个节点上的多线程)上运行一个可以正常运行的程序,并且可以投入更多的CPU它使它更快。
有时候这是真的,但往往不是。关于MPI最重要的事情是,在大多数情况下(除非您进入RMA,这是另一个高级主题),每个MPI进程都有自己独立的内存,与所有其他MPI进程不同。这与所有线程通常共享内存的多线程环境非常不同。这意味着您在并行编程看到的其他复杂性之上添加了一个新问题。现在您必须考虑如何确保您需要处理的数据在正确的时间处于正确的位置。
执行此操作的一种常见方法是确保所有数据已经可用于MPI之外的所有其他进程,例如,通过共享文件系统。然后,流程可以找出他们应该做的工作,并开始使用他们的数据。另一种方法是将单个进程(通常为0级)将重要数据发送到适当的排名。显然,您已经发现了其他方法来优化此过程。 MPI_SCATTER
就是一个很好的例子。
请记住,MPI比多线程更快,这比单线程更快。事实上,有时它可能恰恰相反。通过MPI调用移动数据的成本可能非常高。在尝试使用MPI重写所有代码之前,请确保它实际上是您想要做的。
人们使用MPI的唯一原因不仅仅是通过利用更多处理器来加速他们的代码(尽管有时这是真的)。有时它是因为他们的应用程序试图解决的问题太大而无法适应单个节点的内存。
所有这一切,如果您的问题确实很好地映射到MPI,您可以做您想做的事情。您的应用程序似乎与主/工作类似,处理起来相对简单。只需让您的主人通过他们的工作向您的员工发送非阻止消息,并发布非阻塞MPI_ANY_SOURCE
接收,以便在工作完成后通知他们。当它收到工人的消息时,发出更多的工作要做。