java - 使用 MPI 分配进程

标签 java mpi

我的故事

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

提前致谢

最佳答案

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

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

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

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

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

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

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


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

关于java - 使用 MPI 分配进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28503598/

相关文章:

java - 配置内存或嵌入式数据库来测试生产代码

java - 是否可以只在设计环境中执行代码(android)

c - 如何使用 cmake 编译包含 MPI 的 c 程序

Java小程序访问控制异常: access denied (SocketPermission) - WHERE do I put the fix?

java - 使用 usb4java 向 USB 设备发送消息 - 输入/输出错误

java - 解决jaxb中的循环引用

c - MPI io 按行按进程平均读取文件(而不是按 block 大小)

c - MPI_Bcast - 二维数组中的一行

c++ - 使用 MPI 集体通信发送结构

c++ - 使用 MPI_Send 和 MPI_Recv 从所有处理器发送到根。