C ++ MPI:无法发送任何内容

时间:2016-12-09 14:24:51

标签: c++ mpi

我尝试使用MPI做一个矩阵的总和来做这个,我不知道为什么但是我无法使用MPI_Send发送任何类型的数据,但是我做了什么?'我试图做一个错误信息:

Sending 3 rows to task 1 offset=0
Sending 3 rows to task 2 offset=3
Sending 2 rows to task 3 offset=6
Sending 2 rows to task 4 offset=8
*** An error occurred in MPI_Send
*** reported by process [1047527425,0]
*** on communicator MPI_COMM_WORLD
*** MPI_ERR_RANK: invalid rank
*** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
*** and potentially your MPI job)

这是我的代码:

# include <mpi.h>
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <vector>

#define ROWS 10
#define COLONS 10
#define MASTER 0

using namespace std;

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

    int rows;

    int averow=0;
    int extra=0;
    int offset;
    int numprocs;
    MPI_Status status;
    int matrixA[ROWS][COLONS];
    int matrixB[ROWS][COLONS];
    int matrixC[ROWS][COLONS];

    for (int i = 0; i < COLONS; i++) {
        for (int j = 0; j < ROWS; j++) {
            matrixA[i][j] = rand() % 10;
            matrixB[i][j] = rand() % 10;
        }
    }
    int my_id;

    MPI_Init(&argc, &argv);
    MPI_Comm_size( MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank( MPI_COMM_WORLD, &my_id);
    if (my_id == MASTER) {

        averow = ROWS / numprocs;
        extra = ROWS % numprocs;
        offset = 0;

        /* Send matrix data to the worker tasks */
        for (int dest = 1; dest <= numprocs; dest++) {
            rows = (dest <= extra) ? averow + 1 : averow;
            printf("Sending %d rows to task %d offset=%d\n", rows, dest, offset);
            MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
            MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
            MPI_Send(&matrixA[offset][0], rows * ROWS, MPI_DOUBLE, dest, 1,
            MPI_COMM_WORLD);
            MPI_Send(&matrixB, COLONS * COLONS, MPI_INT, dest, 1,
            MPI_COMM_WORLD);
            offset = offset + rows;
        }

        /* Receive results from worker tasks */
        for (int i = 1; i <= numprocs; i++) {
            int source = i;
            MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
            MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
            MPI_Recv(&matrixC[offset][0], rows * COLONS, MPI_INT, source, 2,
            MPI_COMM_WORLD, &status);
            printf("Received results from task %d\n", source);
        }
    }

    if (my_id != MASTER) {
        MPI_Recv(&offset, 1, MPI_INT, MASTER, 1, MPI_COMM_WORLD, &status);
        MPI_Recv(&rows, 1, MPI_INT, MASTER, 1, MPI_COMM_WORLD, &status);
        MPI_Recv(&matrixA, rows * COLONS, MPI_DOUBLE, MASTER, 1, MPI_COMM_WORLD, &status);
        MPI_Recv(&matrixB, COLONS * COLONS, MPI_DOUBLE, MASTER, 1,
        MPI_COMM_WORLD, &status);

        for (int k = 0; k < COLONS; k++) {
            for (int i = 0; i < rows; i++) {
                matrixC[k][i] = matrixA[k][i] + matrixB[k][i];
            }
        }
        MPI_Send(&offset, 1, MPI_INT, MASTER, 2, MPI_COMM_WORLD);
        MPI_Send(&rows, 1, MPI_INT, MASTER, 2, MPI_COMM_WORLD);
        MPI_Send(&matrixC, rows * COLONS, MPI_DOUBLE, MASTER, 2,
        MPI_COMM_WORLD);
    }
    MPI_Finalize();

    return 0;
}

我在8个流程上运行这个程序。

你知道我在这里做错了什么吗?因为我看不到任何东西。

1 个答案:

答案 0 :(得分:1)

您的代码中存在多处错误:

  1. desti的循环必须为< numprocs。否则你的代码试图发送到排名8,这不存在!
  2. 尽管没有任何MPI_DOUBLE数据,但在某些时候您使用的是double数据类型。发送MPI_INT并收到MPI_DOUBLE也不起作用。
  3. MPI_Send(&matrixA[offset][0], rows * ROWS, ...,应为rows * COLONS
  4. MPI_Send(&matrixB, COLONS * COLONS, ...应该是ROWS * COLONS,也应该是相应的MPI_Recv
  5. 在发送matrixB块的同时转移整个matrixA,根据计算添加情况也没有意义。
  6. 矩阵的第一个维度是,第二个维度是 coumn 。但是,您的添加循环会错误地混合它。
  7. rows <工作人员任务的接收结果中的offset未正确设置。
  8. 我不确定是否发现了所有实际错误,还有一些方面可以得到显着改善:

    1. 具有不同含义的常量ROWS和变量rows非常容易理解代码。
    2. 您的通讯设置不必要地复杂。您可以在许多地方简化模式,例如在本地计算rowsoffset,而不是发送它。但最重要的是,您应该使用集体操作。这更容易推理,也表现得更好。
    3. 在MPI中,主等级通常参与计算。
    4. 不要气馁。初学者很难掌握MPI,并且很容易构建(错误和低效)模式,这些模式可以很容易地用集体来完成。我的建议是:

      1. 从头开始,放弃当前的尝试。
      2. 了解MPI_Scatterv以及MPI_Gatherv。这些是您的示例中唯一需要的通信功能。此外,不需要为主服务器提供单独的代码路径。
      3. 考虑一下您的数据布局。每个等级的矩阵形状是什么。全局矩阵如何映射到本地矩阵。
      4. 使用明确而简洁地描述其含义的变量名称。
      5. 以小步骤编写代码,仔细考虑每一行和参数。
      6. 如果有效,请将其张贴在Code Review上。如果它不起作用或您遇到困难,请发布新问题或更新此问题。在这两种情况下都可以在这里发表评论。