使用MPI分发进程

3

我的故事

我在并行编程方面还是个新手(我只做过一些基本的多线程处理),现在需要将一些已有的多线程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数据类型的转换等(但我想我可以做到这一步)。

然而,真正的问题是,这种解决问题的方法让工作分配非常不平衡,因为它没有考虑某个迭代需要多少工作量。这可能会导致一些麻烦,因为有些迭代可以在不到1秒钟内完成,而其他一些则可能需要几分钟。

我的问题

是否有一种类似于MPI实现中多线程版本的方法?起初,我认为它只是大量的非阻塞点对点通信,但我不知道如何使其工作。我还考虑使用scatter功能,但我对如何正确使用它有太多困扰。

请问有谁可以帮助我澄清一下这个问题吗?
(我确实了解基本的C等)

提前感谢!

1个回答

1
将多线程程序转换为分布式程序时,首先需要问自己的问题是:
通过将数据分布在多个核心/节点等上,我想实现什么?
当初学MPI时,人们经常遇到的一个常见问题是认为可以将在小型共享内存环境中(即在单个节点上进行多线程处理)运行良好的程序投入更多的CPU以使其更快。有时这是正确的,但通常不是。最重要的是要记住MPI的大部分情况下(除非你涉及RMA,这是另一个高级主题),每个MPI进程都有自己独立的内存,与所有其他MPI进程不同。这与多线程环境非常不同,其中所有线程通常共享内存。这意味着您需要解决并行编程中看到的其他复杂性之外的新问题。现在您必须考虑如何确保您需要处理的数据在正确的时间和地点。
一种常见的做法是确保所有数据已经可供MPI以外的所有其他进程访问,例如通过共享文件系统。然后各进程可以找出应该执行的工作并开始处理数据。另一种方式是将重要数据发送给适当的进程,通常是rank 0。显然,您已经发现了其他优化此过程的方法。MPI_SCATTER是一个很好的例子。
请记住,并非总是MPI比多线程更快,而多线程比单线程更快。事实上,有时相反情况会发生。通过MPI调用移动数据的成本可能非常高。在尝试使用MPI重写所有代码之前,请确保这是您真正想要做的。
人们使用MPI的唯一原因不仅仅是通过利用更多处理器来加速代码(尽管有时会这样)。有时候是因为他们应用程序要解决的问题太大,无法适应单个节点的内存。

总之,如果您的问题确实与MPI有很好的映射,那么您可以按照您想要做的方式去做。您的应用程序似乎类似于主/工作进程类型的任务,这相对简单处理。只需让您的主进程向工作进程发送非阻塞消息,并发布一个非阻塞的MPI_ANY_SOURCE接收,以便在完成工作时得到通知。当它从工作者那里收到消息时,请发送更多需要完成的工作。


我仍然怀疑这是否真的是一个好主意,但以前的研究“表明”(我仍然怀疑研究是否真的表明了什么),大规模并行应该适用于这个问题。现在我被指派使用MPI进行实现,这就是我要做的...感谢您的出色回答。 - Mr Tsjolder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接