【问题标题】:MPI_scatter: Invalid buffer pointerMPI_scatter:无效的缓冲区指针
【发布时间】:2015-04-04 21:51:00
【问题描述】:

谁能告诉我我做错了什么,因为我收到了这个错误。 代码:

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

void transpose(int ** p, int row, int col)
{
    int ** tempVar;
    tempVar = (int *)malloc(sizeof(int *)* row);
    int i = 0;
    for (; i < row; i++)
    {
        tempVar[i] = (int *)malloc(sizeof (int *)* col);
        int j = 0;
        while (j < col)
        {
            tempVar[i][j] = p[j][i];
            j++;
        }
    }
    p = tempVar;
}
void main(int argc, char * argv[])
{
    int rank, size;
    MPI_Init(argc, argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    int d[] = { 1000, 1000, 1000, 1000, 1000, 1000 };
    int vt[6] = { 1000, 1000, 1000, 1000, 1000, 1000 };
    int ** p;
    p = (int *)malloc(sizeof(int *)* 6);
    int i = 0;
    int row = 6;
    int col = 6;
    while (i < 6)
    {
        p[i] = (int *)malloc(sizeof(int *)* 6);
        /*int j = 0;
        if (rank == 0)
        {
            while (j < 6)
            {
                scanf("%d", p[i][j]);
                j++;
            }
        }*/
        i++;    
    }
    p[0][0] = 0; p[0][1] =2 ; p[0][2] =3 ; p[0][3] =1 ; p[0][4] =1000 ; p[0][5] =1000 ;
    p[1][0] = 2; p[1][1] = 0; p[1][2] = 1000; p[1][3] = 1000; p[1][4] = 5; p[1][5] = 1000;
    p[2][0] = 3; p[2][1] = 1000; p[2][2] = 0; p[2][3] = 1000; p[2][4] = 1000; p[2][5] = 1;

    p[3][0] = 1; p[3][1] = 1000; p[3][2] = 1000; p[3][3] = 0; p[3][4] = 4; p[3][5] = 3;

    p[4][0] = 1000; p[4][1] = 5; p[4][2] = 1000; p[4][3] = 4; p[4][4] = 0; p[4][5] = 2;

    p[5][0] = 1000; p[5][1] = 1000; p[5][2] = 1; p[5][3] = 3; p[5][4] = 2; p[5][5] = 0;
    int smallest;   
    if (rank == 0)
    {
        //transpose(&p , row , col);
        smallest = 0;
        vt[smallest] = smallest;
        //MPI_Bcast();
    }
    int  vt1, d1;
    vt1 = d1 = 0;

    int roww[6];
    MPI_Scatter(vt, 6, MPI_INT, vt1, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Scatter(d, 6, MPI_INT, d1, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Scatter(p, row *row, MPI_INT,roww, 6, MPI_INT, 0, MPI_COMM_WORLD);
    i = 0;
    while (i < (row*row)/size)
    {
        MPI_Bcast(smallest, 1, MPI_INT, 0, MPI_COMM_WORLD);
        if (vt1 != rank)
        {
            if (roww[smallest] != 1000)
            {   
                if (d1 > roww[smallest])
                    d1 = roww[smallest];
            }
        }

        MPI_Gather(d1, 1, MPI_INT, d, row, MPI_INT, 0, MPI_COMM_WORLD);
        if (rank == 0)
        {
            smallest = d[0];
            int k = 1;
            int index = 0;
            while (k < 6)
            {
                if (d[k] < smallest)
                {
                    smallest = d[k];
                    index = k;
                }
                k++;
            }
            vt[k] = index;

        }
        MPI_Scatter(vt, 6, MPI_INT, vt1, (row) / size, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Scatter(d, 6, MPI_INT, d1, (row) / size, MPI_INT, 0, MPI_COMM_WORLD);
i++;

    }
    MPI_Finalize();
}

我得到的错误是

致命错误:MPI_Scatter 中的致命错误:缓冲区指针无效,错误堆栈:
MPI_Scatter(760): MPI_Scatter(sbuf=0x0085f7ac , scount , MPI_INT , rbuf =0x0000000 , rcount =1, MPI_INT , root= 0 , MPI_COMM_WORLD) 失败

【问题讨论】:

  • p = tempVar 代表调用者执行nothing。结果,这会像筛子一样泄漏内存。
  • 但是这里我只是将 tempVar 的地址分配给 p
  • 不,你不是,你将地址 in tempVar 分配给 p,..这对来电者代表。 p 是这个函数的一个自动变量(不管你是否知道)。该分配对调用方没有任何意义。如果您希望调用者“接收”某些东西,您必须将参数声明为指向类型的指针您要保留的类型发送一个地址,并且通过 dereference 分配:*p = ...。正如transpose 所写的那样,除了分配一些内存、旋转 CPU、执行空分配和泄漏分配的内存之外,什么都不做。
  • 当我使用分散调用时它仍然给我错误
  • 如果您在 MPI 进程之间传递指针(我承认我现在有点困惑您在做什么)停止浪费您的时间。指针对于它们建立的地址空间是本地的; MPI 不保证一个进程的指针在复制到另一个进程的地址空间时会指向任何内容。

标签: c++ multithreading parallel-processing mpi fatal-error


【解决方案1】:

您提供的代码编译时带有许多不容忽视的警告,例如:

 passing argument 2 of ‘MPI_Init’ from incompatible pointer type

仔细查看函数的原型:int* fun(int* b); 如果你调用类似int d;fun(d); 的东西,很可能会失败。如果函数需要指向数据的指针,fun(&amp;d) 可能会更好。在调用 MPI 函数时,此问题多次出现。

更多:函数transpose(int ** p) 尝试通过执行p= tempVar 来修改p。正如@WhozCraig 所暗示的,通过执行int **p;...;transpose(p,...),函数transpose() 范围内的p 副本被修改,但p 不被修改。因此,这个函数的正确原型是transpose(int ***p,...),正确的调用方式是int** p;...;transpose(&amp;p,...);

关于内存分配:您找到了分配二维数组的方法!但是数据在内存中并不连续,因为一次分配一个行。如果您打算使用 MPI_Scatter() 等 MPI 函数,allocating a contiguous 2D array 是正确的选择 (more)。

附加建议:在正确的时间调用free() 以释放内存并避免内存泄漏。 Do not cast the return of malloc()

这里有一段代码应该可以用mpicc main.c -o main -Wall 很好地编译。选项-Wall 启用所有警告。它似乎运行良好,虽然我没有检查结果是否正确。

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

void transpose(int *** p, int row, int col)
{
    int ** tempVar;
    tempVar = malloc(sizeof(int *)* row);
    if (tempVar==NULL){printf("malloc failed\n"); exit (1);}
    tempVar[0] = malloc(sizeof (int )* col*row);
    if (tempVar[0]==NULL){printf("malloc failed\n"); exit (1);}
    int i = 0;
    for (i=0; i < row; i++)
    {
        tempVar[i] = &tempVar[0][col*i];
        int j = 0;
        while (j < col)
        {
            tempVar[i][j] = (*p)[j][i];
            j++;
        }
    }
    free((*p)[0]);
    free(*p);
    *p = tempVar;
}
int main(int argc, char * argv[])
{
    int rank, size;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    int d[] = { 1000, 1000, 1000, 1000, 1000, 1000 };
    int vt[6] = { 1000, 1000, 1000, 1000, 1000, 1000 };
    int ** p;

    int i = 0;
    int row = 6;
    int col = 6;
    p = malloc(sizeof(int *)* row);
    if (p==NULL){printf("malloc failed\n"); exit (1);}
    p[0] = malloc(sizeof(int )* row*col);
    if (p[0]==NULL) {printf("malloc failed\n"); exit (1);}
    while (i < row)
    {
        p[i] = &p[0][i*col];
        /*int j = 0;
        if (rank == 0)
        {
            while (j < 6)
            {
                scanf("%d", p[i][j]);
                j++;
            }
        }*/
        i++;    
    }
    p[0][0] = 0; p[0][1] =2 ; p[0][2] =3 ; p[0][3] =1 ; p[0][4] =1000 ; p[0][5] =1000 ;
    p[1][0] = 2; p[1][1] = 0; p[1][2] = 1000; p[1][3] = 1000; p[1][4] = 5; p[1][5] = 1000;
    p[2][0] = 3; p[2][1] = 1000; p[2][2] = 0; p[2][3] = 1000; p[2][4] = 1000; p[2][5] = 1;

    p[3][0] = 1; p[3][1] = 1000; p[3][2] = 1000; p[3][3] = 0; p[3][4] = 4; p[3][5] = 3;

    p[4][0] = 1000; p[4][1] = 5; p[4][2] = 1000; p[4][3] = 4; p[4][4] = 0; p[4][5] = 2;

    p[5][0] = 1000; p[5][1] = 1000; p[5][2] = 1; p[5][3] = 3; p[5][4] = 2; p[5][5] = 0;
    int smallest;   
    if (rank == 0)
    {
        //transpose(&p , row , col);
        smallest = 0;
        vt[smallest] = smallest;
        //MPI_Bcast();
    }
    int  vt1, d1;
    vt1 = d1 = 0;

    int roww[col];
    MPI_Scatter(vt, 1, MPI_INT, &vt1, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Scatter(d, 1, MPI_INT, &d1, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Scatter(&p[0][0], col, MPI_INT,roww, col, MPI_INT, 0, MPI_COMM_WORLD);
    i = 0;
    while (i < (row*row)/size)
    {
        MPI_Bcast(&smallest, 1, MPI_INT, 0, MPI_COMM_WORLD);
        if (vt1 != rank)
        {
            if (roww[smallest] != 1000)
            {   
                if (d1 > roww[smallest])
                    d1 = roww[smallest];
            }
        }

        MPI_Gather(&d1, 1, MPI_INT, d, 1, MPI_INT, 0, MPI_COMM_WORLD);
        if (rank == 0)
        {
            smallest = d[0];
            int k = 1;
            int index = 0;
            while (k < 6)
            {
                if (d[k] < smallest)
                {
                    smallest = d[k];
                    index = k;
                }
                k++;
            }
            vt[k] = index;

        }
        MPI_Scatter(vt, 1, MPI_INT, &vt1, 1, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Scatter(d, 1, MPI_INT, &d1, 1, MPI_INT, 0, MPI_COMM_WORLD);
        i++;

    }

    free(p[0]);
    free(p);
    MPI_Finalize();
    return 0;
}

【讨论】:

    猜你喜欢
    • 2012-06-09
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-31
    • 1970-01-01
    相关资源
    最近更新 更多