1

I am writing my first program using MPI and I am having hard time trying to properly send data to other processes using MPI_Scatter, modify them and receive the values using MPI_Gather. The code is as follows:

int** matrix;
int m = 2, n = 2;
int status;

// could have been int matrix[2][2];

matrix = malloc(m*sizeof(int*));

for(i = 0; i < m; i++) {
  matrix[i] = malloc(n*sizeof(int));
}

matrix[0][0] = 1;
matrix[0][1] = 2;
matrix[1][0] = 2;
matrix[1][1] = 3;

MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &rank ); 
MPI_Comm_size( MPI_COMM_WORLD, &size );

printf("My name is %d out of %d\n", rank, size);

MPI_Scatter(&matrix, 1, MPI_INT, &status, 1, MPI_INT, 0, MPI_COMM_WORLD);

printf("My name is %d and my status is %d\n", rank, status);

status += 1;

MPI_Gather(&status,1,MPI_INT,&matrix,1,MPI_INT,0,MPI_COMM_WORLD);

The results is as follows:

My name is 0 out of 4
My name is 1 out of 4
My name is 1 and my status is 0
My name is 2 out of 4
My name is 2 and my status is 120
My name is 0 and my status is 17773264
My name is 3 out of 4
My name is 3 and my status is 0

After MPI_Gather when I try to print the content of matrix I get segmentation fault...

Which is not what I expect... I suspect that the problem is I have a 2d array and want to send single values. Is this right? How to correct this?

tomomomo
  • 157
  • 2
  • 13

1 Answers1

3

The reason for the segmentation fault is, that you're allocating a 2D array but there is no guarantee that it uses contiguous memory. So, allocate a 1D array and scatter/gather it. This also explains why some nodes get the wrong data.

You named the receiving variable status which I find misleading, since it'll hold the received value(s). So you'll have to allocate it correctly for the case when a node receives more then one value. Also I'd suggest to rename it to e.g. local_matrix or similar.

Side node: You allocate matrix on all nodes, but you should only allocate on a single node. This can be done by checking the current rank and placing a barrier after the check. Furthermore, I assume that you also print on all nodes, but this code isn't visible. As with the allocation, print should done as well only on one node.

Also have a look at How are MPI_Scatter and MPI_Gather used from C? which explains it pretty well.

Community
  • 1
  • 1
Sebastian
  • 8,046
  • 2
  • 34
  • 58
  • You definitely should *allocate* `matrix` on all nodes, but you may not want to *initialize* it on all nodes (or, more generally, you may want to initialize them differently). – suszterpatt Jan 02 '14 at 21:19
  • No, this is not correct. The matrix may be allocated only on node 0. The other ranks will get `status`, *not* `matrix`. Of course, this only works if all nodes only get a single element of the matrix. – Sebastian Jan 02 '14 at 21:22
  • @suszterpatt, not true. The source arguments to `MPI_Scatter` are _ignored_ in all non-root nodes. The same applies to the destination arguments for `MPI_Gather`. Therefore `matrix` _could_ be allocated in a single process only. – Hristo Iliev Jan 02 '14 at 21:22
  • Ok, now I allocate matrix only on node with rank equal to 0. I also print only on the node with this rank. But the result is the same... My program works if I have a 1d array but not with a 2d array. Maybe there's something wrong with how I pass parameters to MPI functions (with pointers etc.) Edit: So 1d array is the only way out? – tomomomo Jan 02 '14 at 21:31
  • @TomaszZ: As I said: a 2D array may not use contiguous memory, so you'll have to stick to 1D and use offsets. – Sebastian Jan 02 '14 at 21:32
  • @TomaszZ, see [this answer](http://stackoverflow.com/a/16289737/1374437) on how to allocate contiguous memory and still use it as a 2D array. – Hristo Iliev Jan 02 '14 at 21:40
  • @HristoIliev thanks for sharing that since I missed it. – Sebastian Jan 02 '14 at 21:41
  • Thank you @Sebastian Dressler, it works now :) Also, thank you Hristo Iliev but my example is quite simple so 1d array will do. – tomomomo Jan 02 '14 at 22:24