0

Can anybody tell what am I doing wrong due to which I am getting this error. Code:

#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();
}

The error that I am getting is

Fatal Error: fatal error in MPI_Scatter: Invalid buffer pointer, error stack:
MPI_Scatter(760): MPI_Scatter(sbuf=0x0085f7ac , scount , MPI_INT , rbuf =0x0000000 , rcount =1, MPI_INT , root= 0 , MPI_COMM_WORLD) failed

Wesley Bland
  • 8,816
  • 3
  • 44
  • 59
Gardezi
  • 2,692
  • 2
  • 32
  • 62
  • `p = tempVar` does *nothing* on the caller's behalf. And this leaks memory like a sieve as a result. – WhozCraig Feb 05 '15 at 06:08
  • but here I am just assigning the address of tempVar to p – Gardezi Feb 05 '15 at 06:09
  • 1
    No you're not, you're assigning the address *in* `tempVar` to `p`, ..which does *nothing* on the callers behalf. `p` is a automatic variable to this function (whether you knew that or not). That assignment means nothing back on the caller side. If you want the caller to "receive" something you have to declare the parameter to be a pointer-to-type *of the type you want to keep* send an *address*, and assign via *dereference* : `*p = ...`. As written `transpose` does nothing but allocate some memory, spin CPU, perform a nothing assignment, and leak the allocated memory. – WhozCraig Feb 05 '15 at 06:11
  • it still gives me error when I'm using scatter call – Gardezi Feb 05 '15 at 08:16
  • Thats not the only error it gives you, Now you're passing a pointer of the wrong type (`int***`) to transpose (expects `int**`). And the memory leak and ineffective assignment in `transpose` remain. *Stop guessing*. I suspect you need to spend some time learning more about pointers in C++. – WhozCraig Feb 05 '15 at 08:20
  • I commented the transpose because in this if I take the transpose I'll be getting the same matrix and it continues to give me the same error and sorry for not updating the code – Gardezi Feb 05 '15 at 08:25
  • 2
    If you are passing pointers between MPI processes (and I confess I'm a bit confused right now what you *are* doing) stop wasting your time. Pointers are local to the address space in which they are established; MPI does not guarantee that a pointer from one process points to anything when copied to another process's address space. – High Performance Mark Feb 05 '15 at 08:36

1 Answers1

0

The code you provided compiles with lots of warnings that are not to be ignored such as :

 passing argument 2 of ‘MPI_Init’ from incompatible pointer type

Look carefully at the prototype of functions : int* fun(int* b); is likely to fail if you call something like int d;fun(d);. If the function needs a pointer to the data, fun(&d) may work better. This problem occurs many times, as MPI functions are called.

More : the function transpose(int ** p) tries to modify p by doing p= tempVar. As signaled by @WhozCraig, by doing int **p;...;transpose(p,...), a copy of p in the scope of the function transpose() is modified, but not p. Hence, the right prototype of this function is transpose(int ***p,...) and the right way to call it is int** p;...;transpose(&p,...);

Regarding memory allocation : you found a way to allocate 2D array ! But the data is not contiguous in memory since rows are allocated one at a time. If you plan to use MPI functions such as MPI_Scatter(), allocating a contiguous 2D array is the right way to go (more).

Additional advice : call free() at the right time to free the memory and avoid memory leaks. Do not cast the return of malloc()

Here is a piece of code that should compile well with mpicc main.c -o main -Wall. The option -Wall enables all warnings. It seems to run fine, though i did not check if the result is correct.

#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;
}
Community
  • 1
  • 1
francis
  • 9,525
  • 2
  • 25
  • 41