使用 MPI 分配进程

distribution of processes with MPI

我的故事

我是并行编程的新手(除了编写一些基本的多线程程序,我什么也没做)我需要并行化一些多线程 java-code 才能使它 运行 更快。多线程算法简单地生成线程并将它们传递给为我分配线程的操作系统。每个线程的结果可以由一些收集器收集,该收集器还处理信号量等的同步问题并计算所有不同线程的结果总和。多线程代码看起来像这样:

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 等)

提前致谢

将多线程程序转换为分布式程序首先要问自己的问题是:

我试图通过将数据分布到多个 cores/nodes/etc 来完成什么?

人们在开始使用 MPI 时面临的最常见问题之一是认为他们可以采用在小型共享内存环境(即单个节点上的多线程)中运行良好的程序并抛出更多CPU 使其更快。

有时是这样,但通常不是这样。关于 MPI,要记住的最重要的一点是,在大多数情况下(除非您进入 RMA,这是另一个高级主题),每个 MPI 进程都有自己独立的内存,与所有其他 MPI 进程不同。这与所有线程通常共享内存的多线程环境非常不同。这意味着您在并行编程中看到的其他复杂性之上添加了一个新问题。现在你必须考虑如何确保你需要处理的数据在正确的时间出现在正确的地方。

实现此目的的一种常见方法是确保所有数据都已可供 MPI 之外的所有其他进程使用,例如,通过共享文件系统。然后流程就可以弄清楚他们应该做什么工作,并开始使用他们的数据。另一种方法是让单个进程(通常为 0 级)将重要数据发送到适当的级数。显然,您已经发现了其他优化此过程的方法。 MPI_SCATTER 就是一个很好的例子。

请记住,MPI 不一定比多线程快,多线程比单线程快。事实上,有时情况可能恰恰相反。通过 MPI 调用移动数据的成本可能非常高。在尝试使用 MPI 重写所有代码之前,请确保这是您真正想要做的。

人们使用 MPI 的唯一原因不仅仅是通过利用更多处理器来加速他们的代码(尽管有时确实如此)。有时是因为他们的应用程序试图解决的问题太大,无法容纳单个节点的内存。


综上所述,如果您的问题确实很好地映射到 MPI,那么您可以做您想做的事。你的申请好像是master/worker类的工作,处理起来比较简单。只需让您的主人将非阻塞消息与他们的工作一起发送给您的工人,然后 post 一个非阻塞 MPI_ANY_SOURCE 接收,以便在工作完成时收到通知。当它收到工人的消息时,发出更多的工作要做。