【问题标题】:Using MPI_Scatter and MPI_Gather to implement Master-Worker-Model使用 MPI_Scatter 和 MPI_Gather 实现 Master-Worker-Model
【发布时间】:2020-11-20 17:10:30
【问题描述】:

我为图像处理过滤器编写了一个 MPI 程序。该程序的主要目标是使用并行计算将给定的过滤器应用于图像文件。

MPI 程序运行良好,没有任何问题。

现在我想为我的 MPI 程序使用 Master-Worker-Model。 经过一番研究,我发现 MPI_Scatter 和 MPI_Gather 是我需要的命令。

但我不太明白它们是如何工作的。这是我第一次尝试编写代码:

#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv)
{

    // Filters

    MPI_Init(&argc, &argv);

    if(parent == MPI_COMM_NULL)
    {
        MPI_Scatter(); // What are the parameters?

        // Master reads in the image file and distribute it to the workers.
        MPI_File_open();
        MPI_File_read();
        MPI_File_close();
    }
    else
    {
        // After receiving data from the master, worker processes begin their job.

        /* Normally here would be the entire logic of this program.*/
        /* For simplicity I just skip it for readability.*/
        /* The calculcation is exclusively up to the workers.*/
    }

    // After finishing, the results will be sent back to the master.

    MPI_Gather(); // What are the parameters?

    MPI_Finalize(); 
    return 0; 
}

它不会运行,因为它只是第一个原型。我想知道的是我是否理解了Master-Worker-Model的概念。

对代码的一些反馈会很有帮助。

提前致谢。

【问题讨论】:

  • 据我了解,MPI_Comm_spawn 只是创建同一程序的多个副本,并在它们之间建立通信并返回一个相互通信器(可能是一些用于与这些副本通信的对象)(在@987654324 之前使用@?) MPI_Barrier 是一个阻塞代码,它将阻塞进程直到所有进程都到达某个指定点(称为特定函数)(在MPI_Gather? 之前使用)。我无法理解这个:MPI_Intercomm_merge。不过,我的理解可能是错误的。
  • MPI standard document 有一个经理-工人计划的示例(第 10.3.5 节 - 第 383 页)。该示例显示了一个程序如何从仅 1 个进程(管理器)开始创建/生成另一个进程(工作器)并与之交互。一旦创建了工作进程,程序的其余部分将与任何其他 MPI 程序相同。您可以轻松扩展该示例以创建多个工作人员。
  • 如果你的程序只在一台主机上运行(例如你不做分布式计算),我认为多线程会更适合和更容易地解决你的问题。
  • MPI 非常不适合图像处理。特别是如果您的图像只有 1k 像素宽。与您正在执行的大多数计算相比,发送数据需要更多时间。
  • @Aziz 我意识到了这个例子。我的问题是没有 MPI_ScatterMPI_Gather 用于向工作人员分发数据。此外,有人告诉我必须使用MPI_Intercomm_merge。我的 MPI 程序比这个例子更复杂。

标签: c image-processing parallel-processing mpi broadcast


【解决方案1】:

这是一个示例程序,展示了如何执行分散/聚集操作。 请注意,在您的情况下,由于主任务没有做任何工作,因此最适合内部通信器(即使内部通信器上的集体操作的语义并不总是很直观),因此您不需要 MPI_Intercomm_merge() .

#include <stdio.h>
#include <stdbool.h>

#include <mpi.h>

int main(int argc, char *argv[]) {
    MPI_Comm parent, intercomm;
    const int slaves = 2;
    bool master;
    int data[slaves];
    int mydata;
    int i, rank, root;

    MPI_Init(&argc, &argv);
    MPI_Comm_get_parent(&parent);
    master = parent == MPI_COMM_NULL;

    if (master) {
        int errcodes[slaves];
        /* spawn the slaves */
        MPI_Comm_spawn(argv[0], MPI_ARGV_NULL, slaves, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &intercomm, errcodes);

        /* prepare data to be scattered to the slaves */
        for (i=0; i<slaves; i++) {
            data[i] = i;
        }

        /* here we assume there is only one master */
        root = MPI_ROOT;
    } else {
        intercomm = parent;
        root = 0;
    }

    /* scatter data from master to slaves */
    MPI_Scatter(data, 1, MPI_INT, &my-data, 1, MPI_INT, root, intercomm);

    if (!master) {
        /* slaves do their work */
        mydata = mydata + 1;
    }

    /* gather data from slaves to master */
    MPI_Gather(&mydata, 1, MPI_INT, data, 1, MPI_INT, root, intercomm);

    if (master) {
        int i;
        for (i=0; i<slaves; i++) {
            printf("Slave %d returned %d\n", i, data[i]);
        }
    }

    MPI_Comm_disconnect(&intercomm);

    MPI_Finalize();
    return 0;
}

【讨论】:

  • 非常感谢。这将帮助我理解一切是如何运作的。从站的数量在您的代码中是固定的。如果从站的数量是用户定义的,我将如何执行它?
  • 不会有太大变化:不要硬编码从属设备的数量,而是从命令行或配置文件中读取。
  • 好的,我会这样做的。另一件事是,父组的主进程和从组的第一个从进程的等级为 0。这是不允许的。为此,我必须使用 MPI_Intercomm_merge()。此外,只有主进程选择要使用的过滤器并将其发送给从属进程。我认为需要 MPI_Bcast()。
  • 如果您的意思是两个任务在交互器中的排名为 0,那么是的,两个任务的排名为 0,但这些任务位于两个不同的组中(这就是交互器的工作方式),并且由于数据是从主机(例如 A 组中的 0 级)分散到所有从机(例如 B 组中的 0-3 级),然后在对讲机中的 MPI_Scatter() 是最合适的。
  • 你也可以MPI_Bcast()在对讲中从主到从。 root=MPI_ROOT 在主服务器上,root=0 在从服务器上。
猜你喜欢
  • 2013-10-24
  • 2017-05-25
  • 2012-12-01
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2019-03-18
  • 2021-04-08
  • 1970-01-01
相关资源
最近更新 更多