【问题标题】:Passing submatrices from master to slaves MPI将子矩阵从主机传递到从机 MPI
【发布时间】:2018-06-30 04:59:21
【问题描述】:

我正在尝试学习 MPI,但在我的一门课程中遇到了以下问题:

考虑一个维度为 n * n 的矩阵 A,其中每个元素都是整数。给定 2 对索引 (i1,j1) 和 (i2,j2) 在矩阵 A 中找到其元素总和最大的此类维度的子矩阵。

我想要一些关于如何将子矩阵传递给进程的帮助。我应该先计算矩阵中有多少子矩阵并发送到每个进程 N/s?我将如何发送子矩阵?

我写的一些骨架代码:

#include<mpi.h>
#include<stdio.h>
#include<math.h>
#include<assert.h>
#include<iostream>

using namespace std;

#pragma comment (lib, "msmpi.lib")

enum CommunicationTag
{
    COMM_TAG_MASTER_SEND_TASK,
    COMM_TAG_MASTER_SEND_TERMINATE,
    COMM_TAG_SLAVE_SEND_RESULT,
};

void print_matrix(int mat[10][10], int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", mat[i][j]);
        }
        printf("\n");
    }
}

int main(int argc, char *argv[]) {
    //0. Init part, finding rank and number of processes

    int numprocs, rank, rc;
    rc = MPI_Init(&argc, &argv);
    if (rc != MPI_SUCCESS) {
        printf("Error starting MPI program. Terminating \n");
        MPI_Abort(MPI_COMM_WORLD, rc);
    }

    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    printf("I'm rank %d. Num procs %d\n", rank, numprocs); fflush(stdout);


//1. different machine code
    if (rank == 0)
    {
        int n;
        scanf("%d", &n);

        int i1, i2, j1, j2;
        scanf("%d%d%d%d", &i1, &i2, &j1, &j2);

        int mat[10][10];

        //init data
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++) {
                mat[i][j] = (rand() % 100) - 50; //init random between -50 and 49
            }

        print_matrix(mat, n);

//here; how do I pass the submatrices to the processes?
        for (int i = 1; i < numprocs; i++) {
            MPI_Send(&i1, 1, MPI_INT, i, COMM_TAG_MASTER_SEND_TASK, MPI_COMM_WORLD);
            MPI_Send(&i2, 1, MPI_INT, i, COMM_TAG_MASTER_SEND_TASK, MPI_COMM_WORLD);
            MPI_Send(&j1, 1, MPI_INT, i, COMM_TAG_MASTER_SEND_TASK, MPI_COMM_WORLD);
            MPI_Send(&j2, 1, MPI_INT, i, COMM_TAG_MASTER_SEND_TASK, MPI_COMM_WORLD);

//here; how do I pass the submatrices to the processes?
        }
    }
    else {
        //if slave ...

    }
    system("Pause");
}

【问题讨论】:

  • “给定 2 对索引 (i1,j1) 和 (i2,j2) 在矩阵 A 中找到其元素总和最大的此类维度的子矩阵。” - 我不知道要求什么。什么是“这样的维度”?哪些维度?指数是做什么用的?一个小例子会很有帮助。
  • 因此,如果我有一个尺寸为 5x5 的矩阵 A 和两对索引 (0,0) 和 (2,2),我将有一个尺寸为 3x3(9 个元素)的子矩阵。在矩阵 A 中会有 9 个这样的子矩阵。
  • 在使用 MPI 之前有可能进行优化。例如,可以计算线上部分和的矩阵。然后,无论子矩阵的大小是多少,子矩阵的一行之和都是两项之间的差。然后可以在列上应用相同的技巧:部分和和差。最后,计算最大值。
  • @N.Nae:所以i1, j1, i2, j2 的唯一用途是计算i2 - i1j2 - j1 以获得尺寸?
  • 这实际上是一种微不足道的简化,您应该自己解决,而不是作为问题的隐含部分。我建议你编辑你的问题,说一些更直接的话,比如"Given a smaller dimension m (less than n), find the m x m submatrix in matrix A for which it's elements sum is maximum."

标签: c matrix mpi


【解决方案1】:

第一步是停止思考如何使用MPI_Send()。基本解决方案是使用MPI_Bcast()A 传输到所有MPI 进程。

然后将工作向上划分(不需要为此通信,相同的划分逻辑可以在每个进程中运行)。计算每个 MPI 进程中的总和,并使用MPI_Gather() 在主进程中收集它们。选择最大的就完成了。

实际上只需要两个 MPI 操作:Bcast 将输入数据分发到所有进程,以及 Gather 集中结果。

请注意,所有 MPI 进程都需要同步执行集体操作。您只需要if (rank == 0) 即可知道应该由哪个进程加载矩阵并分析 Gathered 结果。

【讨论】:

  • 有点创意,MPI_Allgather()可以换成MPI_Reduce(..., MPI_MAXLOC, ...)
  • @GillesGouaillardet:我同意,我最初开始在我的答案中写下这一点,但后来决定增加复杂性以获得可疑的好处。 OP刚刚开始,所以我决定亲吻。
猜你喜欢
  • 1970-01-01
  • 2014-10-29
  • 1970-01-01
  • 2021-04-25
  • 2018-09-23
  • 2015-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多