Reputation: 11
I have to create an array dynamically using malloc , the root process does this, then the arrays is supposed to be broadcasted to all the other processes who will print it for now, actually requirement is the other processes will change the value of the matrix independently. My main problem is im not able to broadcast the whole array to all the processes.
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int **array;
int rank,size,i,j;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Datatype data_type;
size= 4;
array = (int **)malloc(size*sizeof(int *));
for(i=0;i<size;i++)
array[i] = (int *)malloc(size*sizeof(int));
if(rank==0)
{
int t= 0;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++){
array[i][j]=t++;
printf("%4d",array[i][j]);
}
printf("\n");
}
printf("size is %zu\n",sizeof(array));
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Bcast(&size,1,MPI_INT,0,MPI_COMM_WORLD);
printf("size %d proec %d\n",size,rank);
MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
printf("process %d prainting matrix:\n",rank);
for (i= 0; i <size;i++)
{
for(j= 0; j < size; j++)
printf("%d [%d]\t",array[i][j],rank);
printf("\n");
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
}
Upvotes: 0
Views: 998
Reputation: 2699
The problem is with line
MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);
you should do
for(i=0;i<size;i++)
{
MPI_Bcast((int **)&(array[i][0]),size,MPI_INT,0,MPI_COMM_WORLD);
}
I don't know what was your intent but sizeof(array)
does not return the size of the array but rather the size of an (size_t *)
which is 8 in 64 bits.
Long explanation if you want one.
MPI_Send or MPI_Bcast really send chunk of memories.
To determine these chunks you have to give a beginning (first argument of MPI_Bcast or MPI_Send) then a length (second argument) then the type of data (third argument).
In your example it knows it must send from &(array[0][0])
to &(array[0][0])+(size*size-1)*sizeof(int)
Now when you do
int main(int argc, char **argv)
{
int **array, * array_un;
int rank,size,i,j;
int **array
size= 4;
array = (int **)malloc(size*sizeof(int *));
for(i=0;i<size;i++)
{
array[i] = (int *)malloc(size*sizeof(int));
printf("Ox%X\n",(size_t)array[i]);
}
printf("end array=Ox%X\n",(size_t) &(array[size-1][size-1]));
printf("end pointer=Ox%X\n",(size_t) array+(size*size-1)*sizeof(int));
}
it outputs
Ox13B91A0
Ox13B91C0
Ox13B91E0
Ox13B6B90
end array = Ox13B6B9C
end pointer= Ox13BB06C
As you see end array
and end pointer
are different. If you now look at the adress of each malloc
the increment is 0x20 (which is more than 4*size(int)=10
) then suddenly decrement by 0x2650 !
Successive malloc
allocate the memory with no warranty that the memory are allocated next to each other.
Therefore you cannot send using MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);
because the data between &(array[0][0])
to &(array[0][0])+(size*size-1)*sizeof(int)
does not actually contain the data you want to send.
However one malloc
allocates a chunk of contiguous memory
so you can send MPI_Bcast((int **)&(array[i][0]),size,MPI_INT,0,MPI_COMM_WORLD);
To be thourough
Setting up a send and receive has a cost and sending has a cost. So the less MPI_"something" call you do the better it is.
So your matrix should really be allocated with one malloc
Compare your modified code with this code
#include <mpi.h>
int main(int argc, char **argv)
{
int *array;
int rank,size,i,j;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Datatype data_type;
size= 4;
array = (int *)malloc(size*size*sizeof(int));
if(rank==0)
{
int t= 0;
for(i=0;i<size;i++) { for(j=0;j<size;j++){ array[i*size+j]=t++; } }
}
MPI_Bcast(array,size*size,MPI_INT,0,MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
printf("process %d printing matrix:\n",rank);
for (i= 0; i <size;i++)
{
for(j= 0; j < size; j++)
printf("%d [%d]\t",array[i*size+j],rank);
printf("\n");
}
MPI_Finalize();
}
Upvotes: 1