【问题标题】:MPI matrix multiplication, process not cleaning upMPI矩阵乘法,进程不清理
【发布时间】:2015-12-20 06:21:22
【问题描述】:

我正在尝试使用 MPI 将两个 nxn 矩阵相乘。第二个矩阵 (bb) 被广播到所有“从属”,然后从第一个矩阵 (aa) 发送一行以计算乘积。然后它将答案发送回主进程并存储在乘积矩阵 cc 中。出于某种原因,我收到了错误:

=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   EXIT CODE: 11
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES

我相信主进程正在接收从进程发送的所有消息,反之亦然,所以我不确定这里发生了什么......有什么想法吗?

主要:

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/times.h>
#define min(x, y) ((x)<(y)?(x):(y))
#define MASTER 0

double* gen_matrix(int n, int m);
int mmult(double *c, double *a, int aRows, int aCols, double *b, int bRows, int bCols);

int main(int argc, char* argv[]) {
    int nrows, ncols;
    double *aa;     /* the A matrix */
    double *bb;     /* the B matrix */
    double *cc1;    /* A x B computed */
    double *buffer; /* Row to send to slave for processing */
    double *ans;    /* Computed answer for master */
    int myid, numprocs;
    int i, j, numsent, sender;
    int row, anstype;
    double starttime, endtime;
    MPI_Status status;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    if (argc > 1) {
        nrows = atoi(argv[1]);
        ncols = nrows;
        if (myid == 0) {
            /* Master Code */
            aa = gen_matrix(nrows, ncols);
            bb = gen_matrix(ncols, nrows);
            cc1 = malloc(sizeof(double) * nrows * nrows);
            starttime = MPI_Wtime();
            buffer = (double*)malloc(sizeof(double) * ncols);
            numsent = 0;
            MPI_Bcast(bb, ncols*nrows, MPI_DOUBLE, MASTER, MPI_COMM_WORLD); /*broadcast bb to all slaves*/
            for (i = 0; i < min(numprocs-1, nrows); i++) {                  /*for each process or row*/
                for (j = 0; j < ncols; j++) {                               /*for each column*/
                    buffer[j] = aa[i * ncols + j];                          /*get row of aa*/
                }
                MPI_Send(buffer, ncols, MPI_DOUBLE, i+1, i+1, MPI_COMM_WORLD); /*send row to slave*/
                numsent++;                                                     /*increment number of rows sent*/
            }
            ans = (double*)malloc(sizeof(double) * ncols);
            for (i = 0; i < nrows; i++) {
                MPI_Recv(ans, ncols, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG,
                         MPI_COMM_WORLD, &status);
                sender = status.MPI_SOURCE;
                anstype = status.MPI_TAG;

                for (i = 0; i < ncols; i++){
                    cc1[(anstype-1) * ncols + i] = ans[i];
                }

                if (numsent < nrows) {
                    for (j = 0; j < ncols; j++) {
                        buffer[j] = aa[numsent*ncols + j];
                    }
                    MPI_Send(buffer, ncols, MPI_DOUBLE, sender, numsent+1,
                             MPI_COMM_WORLD);
                    numsent++;
                } else {
                    MPI_Send(MPI_BOTTOM, 0, MPI_DOUBLE, sender, 0, MPI_COMM_WORLD);
                }
            }

            endtime = MPI_Wtime();
            printf("%f\n",(endtime - starttime));
        } else {
            /* Slave Code */
            buffer = (double*)malloc(sizeof(double) * ncols);
            bb = (double*)malloc(sizeof(double) * ncols*nrows);
            MPI_Bcast(bb, ncols*nrows, MPI_DOUBLE, MASTER, MPI_COMM_WORLD); /*get bb*/
            if (myid <= nrows) {
                while(1) {
                    MPI_Recv(buffer, ncols, MPI_DOUBLE, MASTER, MPI_ANY_TAG, MPI_COMM_WORLD, &status); /*recieve a row of aa*/
                    if (status.MPI_TAG == 0){
                        break;
                    }

                    row = status.MPI_TAG; /*get row number*/
                    ans = (double*)malloc(sizeof(double) * ncols);
                    for (i = 0; i < ncols; i++){
                        ans[i]=0.0;
                    }
                    for (i=0; i<nrows; i++){
                        for (j = 0; j < ncols; j++) { /*for each column*/
                            ans[i] += buffer[j] * bb[j * ncols + i];
                        }
                    }
                    MPI_Send(ans, ncols, MPI_DOUBLE, MASTER, row, MPI_COMM_WORLD);
                }
            }
        } /*end slave code*/
    } else {
        fprintf(stderr, "Usage matrix_times_vector <size>\n");
    }
    MPI_Finalize();
    return 0;
}

【问题讨论】:

  • 在您的最终发送中,您只发送 0 个实数,在等待 ncols 时,这可能会导致问题。最好事先使用 MPI_Probe 来确定消息的大小。更好的是,事先弄清楚分区,这样您就知道要接收多少行。

标签: c matrix parallel-processing mpi


【解决方案1】:

此错误消息通常意味着至少有一个 MPI 进程崩溃,整个 MPI 作业随后中止。它可能由任何类型的错误引起,但大多数情况下,它是由错误的内存访问引起的分段错误。

我没有仔细看代码,所以我不知道逻辑是否有效等,但我可以说这一行有问题:

MPI_Recv(&ans, nrows, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG,
         MPI_COMM_WORLD, &status);

确实,这里有两个问题:

  1. &amp;ans**double,这不是你想要的,我猜你想要 ans
  2. ans 尚未分配,因此不能用作接收缓冲区

先尝试解决这个问题,看看会发生什么。

编辑:在您的新代码上分配ans,如下所示:

ans = (double*)malloc(sizeof(double) * ncols);

然后你像这样初始化它:

for (i = 0; i < nrows; i++) {
    ans[i]=0.0;
}

并像这样使用它:

MPI_Send(ans, nrows, MPI_DOUBLE, MASTER, row, MPI_COMM_WORLD);

MPI_Recv(ans, nrows, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG,
         MPI_COMM_WORLD, &status);

这不连贯:ans 的大小是ncols 还是nrows

你的新错误信息是什么?

【讨论】:

  • &ans 实际上是一个 *double,它代表一维数组中的“矩阵”。我相信分配不应该是我传递地址的问题,但是我可能是错的。但是,我还是分配了它,但我仍然收到同样的错误。
  • 你声明了double *ans; ,所以&amp;ans是一个指向ans的指针,而ans是一个double*,因此这意味着&amp;ans是一个指向@987654340的指针@又名double**。我再说一遍,您没有为接收缓冲区分配内存。也许您现在已经完成了,如果是这样,只需使用您的新代码编辑问题。顺便说一句,您还在发送端使用&amp;ans,这也是错误的。最后,如果您想使用&amp; 更清楚地表明您使用了指针,请使用&amp;ans[0]
  • 对,不知道我在想什么。自从我用 C 编码以来已经有一段时间了。我修复了它并编辑了上面的代码。我不再遇到同样的错误,但是它似乎仍然挂在某些东西上,因为它没有退出..
  • 在我的代码中,ncols 总是等于 nrows,否则程序将退出。但你是对的,理想情况下它应该是 ncols (我编辑了我的代码以反映这一点)。这次没有错误,代码只是不会退出。此外,我的 cc1(生成的矩阵)只有前 4 个索引(4x4 的第一行)的值(正确的),然后其余的仍然是 0。
  • 哇...我刚刚意识到我在一个已经在使用 i 的 for 循环中重用了“i”。修复了这个问题,我的代码现在可以工作了。感谢您的帮助!
猜你喜欢
  • 2013-12-23
  • 2018-09-08
  • 2017-10-30
  • 1970-01-01
  • 2012-11-04
  • 2014-04-21
  • 2015-04-03
  • 2017-10-12
  • 2016-01-23
相关资源
最近更新 更多