使用 MPI 分配进程

Posted

技术标签:

【中文标题】使用 MPI 分配进程【英文标题】:distribution of processes with MPI 【发布时间】:2015-04-14 17:32:38 【问题描述】:

我的故事

我是并行编程的初学者(除了编写一些基本的多线程东西外,我什么也没做),我需要并行化一些多线程 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 等)

提前致谢

【问题讨论】:

【参考方案1】:

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

我想通过跨多个核心/节点/等分布数据来实现什么?

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

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

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

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

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


话虽如此,如果您的问题确实可以很好地映射到 MPI,那么您可以做您想做的事情。您的应用程序似乎类似于 master/worker 类型的工作,处理起来相对简单。只需让您的主人向您的工作人员发送非阻塞消息,并发布非阻塞MPI_ANY_SOURCE 接收,以便在工作完成时通知它。当它从工人那里得到消息时,发出更多的工作要做。

【讨论】:

我自己仍然怀疑这是否真的是一个好主意,但以前的研究“表明”(我仍然怀疑研究是否确实表明)大规模并行应该适用于这个问题。我现在被分配使用 MPI 进行实施,这就是我要做的……感谢您的出色回答。

以上是关于使用 MPI 分配进程的主要内容,如果未能解决你的问题,请参考以下文章

MPI中每个进程的随机数

验证远程主机以运行 ms-mpi 进程

与不同大小数据类型的 MPI 通信

在MPI C中为每个进程生成随机数

用 MPI IO 写几个分布式数组

为啥我会收到使用 MPI 屏障 [c++] 的致命错误