I'm a newby in MPI and I'm trying to learn how to use MPI_Type_create_subarray in order to apply it in my projects.
I've spent lots of time searching for a tutorial which could fits my needing, but without success.
So I've tried to generalize the concept in How to use MPI_Type_create_subarray to 3D arrays, but something is still missing.
In particular my code return a Segmentation Fault error or shows wrong data when I try to see results.
I can't understand where I made a mistake
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void printarr(int ***data, int nx, int ny, int nz, char *str);
int ***allocarray(int nx, int ny, int nz);
int main(int argc, char **argv) {
/* array sizes */
const int bigsize =10;
const int subsize_x =2; const int subsize_y =2; const int subsize_z =2;
/* communications parameters */
const int sender =0;
const int receiver=1;
const int ourtag =2;
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < receiver+1) {
if (rank == 0)
fprintf(stderr,"%s: Needs at least %d processors.\n", argv[0], receiver+1);
MPI_Finalize();
return 1;
}
MPI_Datatype mysubarray;
int starts[3] = {0,0,0};
int subsizes[3] = {subsize_x,subsize_y,subsize_z};
int bigsizes[3] = {bigsize, bigsize, 3};
MPI_Type_create_subarray(3, bigsizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &mysubarray);
MPI_Type_commit(&mysubarray);
if (rank == sender) {
int ***bigarray = allocarray(bigsize,bigsize,3);
for (int k=0; k<3; k++)
for (int j=0; j<bigsize; j++)
for(int i=0; i< bigsize; i++) {
bigarray[k][j][i] = k*(bigsize*bigsize)+j*bigsize+i;
}
printarr(bigarray, bigsize, bigsize, 3, " Sender: Big array ");
MPI_Send(&(bigarray[0][0][0]), 1, mysubarray, receiver, ourtag, MPI_COMM_WORLD);
MPI_Type_free(&mysubarray);
free(bigarray);
} else if (rank == receiver) {
int ***subarray = allocarray(subsize_x,subsize_y,subsize_z);
MPI_Recv(&(subarray[0][0][0]), subsizes[0]*subsizes[1]*subsizes[2], MPI_INT, sender, ourtag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printarr(subarray, subsize_x, subsize_y, subsize_z, " Receiver: Subarray -- after receive");
free(subarray);
}
MPI_Finalize();
return 0;
}
void printarr(int ***data, int nx, int ny, int nz, char *str) {
printf("-- %s --\n", str);
for(int k=0; k<nz; k++) {
printf("\n\n-----%d------\n",k);
for (int j=0; j<ny;j++) {
for (int i=0; i<nx; i++) {
printf("%3d ", data[k][j][i]);
}
printf("\n");
}
}
}
int ***allocarray(int nx, int ny, int nz) {
int*** arr = (int***)malloc(sizeof(int**)*nz);
for(int k = 0; k < nz; k++) {
arr[k]= (int**)malloc(sizeof(int*)*ny);
for(int j = 0; j< ny; j++){
arr[k][j] = (int*)malloc(sizeof(int)*nx);
for(int i = 0; i < nx; i++){
arr[k][j][i] = 0;
}
}
}
return arr;
}
nzint**elements plusnz1D-arrays ofnyint*elements plusnz*nyintarrays ofnxintelements. All in all1+nz+nz*ny1D arrays, each being an isolated single chunk of memory on its own, as opposed to a real 3D-array which would be one array, that is one chunk of continuous memory.bigarrayof my application (the real ones, not the one in this example) is256*512*1024*2 doubleentries wide, so it's mandatory for me to allocate it dynamically. Can you suggest me a declaration which could fits my needing? Or another way to scatter the data properly among all my processors ?allocarrayand analogue function given by the example you linked. The example in fact allocates one chunk of memory holding allints:int *data = malloc(n*n*sizeof(int));256*512*1024*2" a 4D-array?2is to account the fact that arecomplexnumbers. I must use it because, later in my code, I employ a library which can handle complex just in this way